TABLE OF CONTENTS
- ABINIT/m_ddb
- m_ddb/asr_t
- m_ddb/asrq0_apply
- m_ddb/asrq0_free
- m_ddb/carteig2d
- m_ddb/carttransf
- m_ddb/chkin9
- m_ddb/ddb_bcast
- m_ddb/ddb_can_merge_blocks
- m_ddb/ddb_copy
- m_ddb/ddb_diagoq
- m_ddb/ddb_free
- m_ddb/ddb_from_file
- m_ddb/ddb_get_asrq0
- m_ddb/ddb_get_block
- m_ddb/ddb_get_d1matr
- m_ddb/ddb_get_d2eig
- m_ddb/ddb_get_d2matr
- m_ddb/ddb_get_d3matr
- m_ddb/ddb_get_dchidet
- m_ddb/ddb_get_dielt
- m_ddb/ddb_get_dielt_zeff
- m_ddb/ddb_get_etotal
- m_ddb/ddb_get_gred
- m_ddb/ddb_get_pel
- m_ddb/ddb_get_quadrupoles
- m_ddb/ddb_get_strten
- m_ddb/ddb_init
- m_ddb/ddb_lw_copy
- m_ddb/ddb_malloc
- m_ddb/ddb_malloc_d2eig
- m_ddb/ddb_merge_blocks
- m_ddb/ddb_read_block_txt
- m_ddb/ddb_read_d0E_nc
- m_ddb/ddb_read_d1E_nc
- m_ddb/ddb_read_d2E_nc
- m_ddb/ddb_read_d2eig
- m_ddb/ddb_read_d2eig_nc
- m_ddb/ddb_read_d2eig_txt
- m_ddb/ddb_read_d3E_nc
- m_ddb/ddb_read_nc
- m_ddb/ddb_read_txt
- m_ddb/ddb_set_brav
- m_ddb/ddb_set_d1matr
- m_ddb/ddb_set_d2eig
- m_ddb/ddb_set_d2eig_reshape
- m_ddb/ddb_set_d2matr
- m_ddb/ddb_set_d3matr
- m_ddb/ddb_set_etotal
- m_ddb/ddb_set_gred
- m_ddb/ddb_set_pel
- m_ddb/ddb_set_qpt
- m_ddb/ddb_set_strten
- m_ddb/ddb_set_typ
- m_ddb/ddb_symmetrize_and_transform
- m_ddb/ddb_to_dtset
- m_ddb/ddb_type
- m_ddb/ddb_write
- m_ddb/ddb_write_block_txt
- m_ddb/ddb_write_d2eig
- m_ddb/ddb_write_d2eig_nc
- m_ddb/ddb_write_d2eig_txt
- m_ddb/ddb_write_nc
- m_ddb/ddb_write_txt
- m_ddb/dtchi
- m_ddb/dtech9
- m_ddb/dtqdrp
- m_ddb/gamma9
- m_ddb/lwcart
- m_ddb/merge_ddb
- m_ddb/nlopt
- m_ddb/rdddb9
- m_ddb/symdm9
ABINIT/m_ddb [ Modules ]
NAME
m_ddb
FUNCTION
This module contains the declaration of data types and methods used to handle the blocks of data in DDB files: blkval, nrm, qpt, flg, and associated dimensions Main entry point for client code that needs to read the DDB data.
COPYRIGHT
Copyright (C) 2011-2024 ABINIT group (MJV, XG, MT, MM, MVeithen, MG, PB, JCC, SP, GA, MMignolet) This file is distributed under the terms of the GNU General Public License, see ~abinit/COPYING or http://www.gnu.org/copyleft/gpl.txt .
SOURCE
19 #if defined HAVE_CONFIG_H 20 #include "config.h" 21 #endif 22 23 #include "abi_common.h" 24 25 module m_ddb 26 27 use defs_basis 28 use m_abicore 29 use m_errors 30 use m_xmpi 31 use m_ddb_hdr 32 use m_dtset 33 use m_nctk 34 #ifdef HAVE_NETCDF 35 use netcdf 36 #endif 37 38 use m_io_tools, only : iomode_from_fname 39 use defs_datatypes, only : pseudopotential_type 40 use m_fstrings, only : sjoin, itoa, ktoa, endswith 41 use m_numeric_tools, only : mkherm 42 use m_symtk, only : mati3inv, matr3inv, littlegroup_q, symatm 43 use m_io_tools, only : get_unit 44 use m_copy, only : alloc_copy 45 use m_geometry, only : phdispl_cart2red, mkrdim, xred2xcart, metric 46 use m_crystal, only : crystal_t, crystal_init 47 use m_dynmat, only : cart29, d2sym3, cart39, d3sym, chneu9, asria_calc, asria_corr, asrprs, dfpt_phfrq, sytens 48 use m_pawtab, only : pawtab_type, pawtab_nullify, pawtab_free 49 use m_psps, only : psps_copy, psps_free 50 51 implicit none 52 53 private 54 55 public :: rdddb9 ! This routine reads the derivative database entirely, 56 public :: nlopt ! Output of all quantities related to third-order derivatives of the energy. 57 public :: chkin9 58 public :: carttransf ! Transform a second-derivative matrix (EIG2D) from reduced 59 ! coordinates to cartesian coordinates. 60 public :: lwcart ! Transform a 3rd order derivative tensor (long-wave) from reduced (actually 61 ! mixed since strain derivatives are already in cartesian) to cartesian 62 ! coordinates 63 public :: ddb_lw_copy ! Copy the ddb object after reading the long wave 3rd order derivatives 64 ! into a new ddb_lw and resizes ddb as for 2nd order derivatives 65 66 public :: symdm9 67 68 real(dp),public,parameter :: DDB_QTOL=2.0d-8 69 ! Tolerance for the identification of two wavevectors
m_ddb/asr_t [ Types ]
NAME
asr_t
FUNCTION
Object used to enforce the acoustic sum rule from the Dynamical matrix at Gamma. Wraps several approaches that can be activated via the `asr` option.
SOURCE
365 type,public :: asrq0_t 366 367 integer :: iblok = 0 368 ! Index of the Gamma block in the DDB. 369 ! Set to 0 if no block was found. Client code can use this flag to understand 370 ! if ASR can be enforced. 371 372 integer :: asr 373 ! Option for the application of the ASR (input variable). 374 375 integer :: natom 376 ! Number of atoms. 377 378 real(dp),allocatable :: d2asr(:,:,:,:,:) 379 ! d2asr,(2,3,natom,3,natom)) 380 ! In case the interatomic forces are not calculated, the 381 ! ASR-correction (d2asr) has to be determined here from the Dynamical matrix at Gamma. 382 383 ! singular, uinvers and vtinvers are allocated and used only if asr in [3,4] 384 ! i.e. Rotational invariance for 1D and 0D systems. dims=3*natom*(3*natom-1)/2 385 real(dp),allocatable :: singular(:) 386 ! singular,(1:dims)) 387 388 real(dp),allocatable :: uinvers(:,:) 389 ! uinvers,(1:dims,1:dims)) 390 391 real(dp),allocatable :: vtinvers(:,:) 392 ! vtinvers,(1:dims,1:dims)) 393 394 contains 395 396 procedure :: apply => asrq0_apply 397 ! Impose the acoustic sum rule based on the q=0 block found in the DDB file. 398 399 procedure :: free => asrq0_free 400 ! Free memory 401 402 end type asrq0_t
m_ddb/asrq0_apply [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
asrq0_apply
FUNCTION
Impose the acoustic sum rule based on the q=0 block found in the DDB file.
INPUTS
asrq0<asrq0_t>=Object for the treatment of the ASR based on the q=0 block found in the DDB file. natom=Number of atoms per unit cell. mpert=Maximum number of perturbation (reported in ddb%mpert) msize=Maximum size of array ddb%val xcart(3,natom)=Atomic positions in Cartesian coordinates
SIDE EFFECTS
d2cart=matrix of second derivatives of total energy, in cartesian coordinates Input: Values stored in ddb% Output: Changed to enforce ASR.
SOURCE
4481 subroutine asrq0_apply(asrq0, natom, mpert, msize, xcart, d2cart) 4482 4483 !Arguments ------------------------------- 4484 !scalars 4485 integer,intent(in) :: natom, msize, mpert 4486 class(asrq0_t),intent(inout) :: asrq0 4487 !arrays 4488 real(dp),intent(in) :: xcart(3,natom) 4489 real(dp),intent(inout) :: d2cart(2,msize) 4490 4491 ! ************************************************************************ 4492 4493 if (asrq0%asr /= 0 .and. asrq0%iblok == 0) then 4494 ABI_WARNING("asr != 0 but DDB file does not contain q=Gamma. D(q) cannot be corrected") 4495 return 4496 end if 4497 4498 select case (asrq0%asr) 4499 case (0) 4500 return 4501 case (1,2,5) 4502 call asria_corr(asrq0%asr, asrq0%d2asr, d2cart, mpert, natom) 4503 case (3,4) 4504 ! Impose acoustic sum rule plus rotational symmetry for 0D and 1D systems 4505 call asrprs(asrq0%asr,2,3,asrq0%uinvers,asrq0%vtinvers,asrq0%singular,d2cart,mpert,natom,xcart) 4506 case default 4507 ABI_ERROR(sjoin("Wrong value for asr:", itoa(asrq0%asr))) 4508 end select 4509 4510 end subroutine asrq0_apply
m_ddb/asrq0_free [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
asrq0_free
FUNCTION
Free dynamic memory
SOURCE
4524 subroutine asrq0_free(asrq0) 4525 4526 !Arguments ------------------------------- 4527 class(asrq0_t),intent(inout) :: asrq0 4528 4529 ! ************************************************************************ 4530 4531 ! real 4532 ABI_SFREE(asrq0%d2asr) 4533 ABI_SFREE(asrq0%singular) 4534 ABI_SFREE(asrq0%uinvers) 4535 ABI_SFREE(asrq0%vtinvers) 4536 4537 end subroutine asrq0_free
m_ddb/carteig2d [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
carteig2d
FUNCTION
Transform a second-derivative matrix (EIG2D) from reduced coordinates to cartesian coordinates
INPUTS
blkflg(3,mpert,3,mpert,nblok)= ( 1 if the element of the dynamical matrix has been calculated ; 0 otherwise ) blkval(2,3,mpert,3,mpert,nblok)=DDB values gprimd(3,3)=basis vector in the reciprocal space iblok=number of the blok that will be transformed mpert =maximum number of ipert natom=number of atom nblok=number of blocks (dimension of blkflg and blkval) rprimd(3,3)=basis vector in the real space
OUTPUT
carflg(3,mpert,3,mpert)= ( 1 if the element of the cartesian 2DTE matrix has been calculated correctly ; 0 otherwise ) d2cart(2,3,mpert,3,mpert)= dynamical matrix, effective charges, dielectric tensor,.... all in cartesian coordinates
SOURCE
3153 subroutine carteig2d(blkflg,blkval,carflg,d2cart,gprimd,iblok,mpert,natom,nblok,rprimd) 3154 3155 !Arguments ------------------------------- 3156 !scalars 3157 integer,intent(in) :: iblok,mpert,natom,nblok 3158 !arrays 3159 integer,intent(in) :: blkflg(3,mpert,3,mpert,nblok) 3160 integer,intent(out) :: carflg(3,mpert,3,mpert) 3161 real(dp),intent(in) :: blkval(2,3,mpert,3,mpert,nblok),gprimd(3,3),rprimd(3,3) 3162 real(dp),intent(out) :: d2cart(2,3,mpert,3,mpert) 3163 3164 !Local variables ------------------------- 3165 !scalars 3166 integer :: idir1,idir2,ii,ipert1,ipert2 3167 !arrays 3168 integer :: flg1(3),flg2(3) 3169 real(dp) :: vec1(3),vec2(3) 3170 3171 ! ********************************************************************* 3172 3173 ! First, copy the data blok in place. 3174 d2cart(:,:,:,:,:)=blkval(:,:,:,:,:,iblok) 3175 3176 ! Cartesian coordinates transformation (in two steps) 3177 ! First step 3178 do ipert1=1,mpert 3179 do ipert2=1,mpert 3180 do ii=1,2 3181 do idir1=1,3 3182 do idir2=1,3 3183 vec1(idir2)=d2cart(ii,idir1,ipert1,idir2,ipert2) 3184 ! Note here blkflg 3185 flg1(idir2)=blkflg(idir1,ipert1,idir2,ipert2,iblok) 3186 end do 3187 call cart39(flg1,flg2,gprimd,ipert2,natom,rprimd,vec1,vec2) 3188 do idir2=1,3 3189 d2cart(ii,idir1,ipert1,idir2,ipert2)=vec2(idir2) 3190 ! And here carflg 3191 carflg(idir1,ipert1,idir2,ipert2)=flg2(idir2) 3192 end do 3193 end do 3194 end do 3195 end do 3196 end do 3197 3198 ! Second step 3199 do ipert1=1,mpert 3200 do ipert2=1,mpert 3201 do ii=1,2 3202 do idir2=1,3 3203 do idir1=1,3 3204 vec1(idir1)=d2cart(ii,idir1,ipert1,idir2,ipert2) 3205 ! Note here carflg 3206 flg1(idir1)=carflg(idir1,ipert1,idir2,ipert2) 3207 end do 3208 call cart39(flg1,flg2,gprimd,ipert1,natom,rprimd,vec1,vec2) 3209 do idir1=1,3 3210 d2cart(ii,idir1,ipert1,idir2,ipert2)=vec2(idir1) 3211 ! And here carflg again 3212 carflg(idir1,ipert1,idir2,ipert2)=flg2(idir1) 3213 end do 3214 end do 3215 end do 3216 end do 3217 end do 3218 3219 end subroutine carteig2d
m_ddb/carttransf [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
carttransf
FUNCTION
Transform a second-derivative matrix (EIG2D) from reduced coordinates to cartesian coordinates.
INPUTS
blkflg(msize,nblok)= ( 1 if the element of the dynamical matrix has been calculated ; 0 otherwise ) gprimd(3,3)=basis vector in the reciprocal space iqpt = number of the Q-point currently used mband = maximal number of bands mpert = maximum number of ipert msize = size of the EIG2D arrays (3*mpert*3*mpert) natom = number of atom nblok = number of bloks in blkflg nkpt = number of K-points rprimd(3,3) = basis vector in the real space
OUTPUT
carflg(3,mpert,3,mpert)= ( 1 if the element of the cartesian EIG2D matrix has been calculated correctly ; 0 otherwise ) SIDE EFFECT blkval2(2,msize,mband,nkpt)=Second order eigenvalues (EIG2D) is transformed from reduced coordinates to cartesian coordinates
SOURCE
3053 subroutine carttransf(blkflg,blkval2,carflg,gprimd,iqpt,mband, mpert,msize,natom,nblok,nkpt,rprimd) 3054 3055 !Arguments ------------------------------- 3056 !scalars 3057 integer,intent(in) :: mband,msize 3058 integer,intent(in) :: iqpt 3059 integer,intent(in) :: mpert,nblok 3060 integer,intent(inout) :: natom,nkpt 3061 !arrays 3062 integer,intent(in) :: blkflg(msize,nblok) 3063 integer,intent(out) :: carflg(3,mpert,3,mpert) 3064 real(dp),intent(in) :: gprimd(3,3),rprimd(3,3) 3065 real(dp),intent(inout) :: blkval2(2,msize,mband,nkpt) 3066 3067 !Local variables------------------------------- 3068 !scalars 3069 integer :: iatom1,iatom2,iband,idir1,idir2,ikpt, index 3070 !arrays 3071 real(dp),allocatable :: blkflgtmp(:,:,:,:,:), blkval2tmp(:,:,:,:,:,:), d2cart(:,:,:,:,:) 3072 3073 ! ********************************************************************* 3074 3075 ! Start by allocating local arrays 3076 ABI_MALLOC(blkflgtmp,(3,mpert,3,mpert,1)) 3077 ABI_MALLOC(blkval2tmp,(2,3,mpert,3,mpert,1)) 3078 ABI_MALLOC(d2cart,(2,3,mpert,3,mpert)) 3079 3080 ! Begin by formating the arrays to be compatible with cart29 3081 ! Then call cart29 to transform the arrays in cartesian coordinates 3082 ! Finally reformat the cartesian arrays in old format 3083 do ikpt=1,nkpt 3084 do iband=1,mband 3085 3086 do idir1=1,3 3087 do iatom1=1,mpert 3088 do idir2=1,3 3089 do iatom2=1,mpert 3090 index = idir1 + 3*((iatom1 - 1) + natom * ((idir2-1)+3*(iatom2-1))) 3091 blkflgtmp(idir1,iatom1,idir2,iatom2,1) = blkflg(index,iqpt) 3092 blkval2tmp(:,idir1,iatom1,idir2,iatom2,1) = blkval2(:,index,iband,ikpt) 3093 end do 3094 end do 3095 end do 3096 end do 3097 3098 ! The 1sin the argument of cart29 are respectively iblok and nblok. We are doing only one blok. 3099 call carteig2d(blkflg(:,iqpt),blkval2tmp,carflg,d2cart,gprimd,1,mpert,natom,1,rprimd) 3100 3101 do idir1=1,3 3102 do iatom1=1,mpert 3103 do idir2=1,3 3104 do iatom2=1,mpert 3105 index = idir1 + 3*((iatom1 - 1) + natom * ((idir2-1)+3*(iatom2-1))) 3106 blkval2(:,index,iband,ikpt) = d2cart(:,idir1,iatom1,idir2,iatom2) 3107 end do 3108 end do 3109 end do 3110 end do 3111 3112 end do 3113 end do 3114 3115 ABI_FREE(blkflgtmp) 3116 ABI_FREE(blkval2tmp) 3117 ABI_FREE(d2cart) 3118 3119 end subroutine carttransf
m_ddb/chkin9 [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
chkin9
FUNCTION
Check the value of some input parameters. Send error message and stop if needed. Also transform the meaning of atifc
INPUTS
atifc(natom)=list of the atom ifc to be analysed natifc= number of atom ifc to be analysed natom= number of atoms
OUTPUT
atifc(natom) = atifc(ia) equals 1 if the analysis of ifc has to be done for atom ia; otherwise 0.
NOTES
Only for one processor (no use of wrtout)
SOURCE
2185 subroutine chkin9(atifc,natifc,natom) 2186 2187 !Arguments ------------------------------- 2188 !scalars 2189 integer,intent(in) :: natifc,natom 2190 !arrays 2191 integer,intent(inout) :: atifc(natom) 2192 2193 !Local variables ------------------------- 2194 !scalars 2195 integer :: iatifc 2196 character(len=500) :: msg 2197 !arrays 2198 integer,allocatable :: work(:) 2199 2200 ! ********************************************************************* 2201 2202 if(natifc>natom)then 2203 write(msg, '(a,i0,3a,i0,3a)' )& 2204 'The number of atom ifc in the input files',natifc,',',ch10,& 2205 'is larger than the number of atoms',natom,'.',ch10,& 2206 'Action: change natifc in the input file.' 2207 ABI_ERROR(msg) 2208 end if 2209 2210 if(natifc>=1)then 2211 ABI_MALLOC(work,(natom)) 2212 work(:)=0 2213 2214 do iatifc=1,natifc 2215 if(atifc(iatifc)<=0.or.atifc(iatifc)>natom)then 2216 write(msg, '(a,i0,5a,i0,3a)' )& 2217 'For iatifc=',iatifc,', the number of the atom ifc to be ',ch10,& 2218 'analysed is not valid : either negative, ',ch10,& 2219 'zero, or larger than natom =',natom,'.',ch10,& 2220 'Action: change atifc in your input file.' 2221 ABI_ERROR(msg) 2222 end if 2223 work(atifc(iatifc))=1 2224 end do 2225 2226 atifc(1:natom)=work(:) 2227 ABI_FREE(work) 2228 end if 2229 2230 end subroutine chkin9
m_ddb/ddb_bcast [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_bcast
FUNCTION
MPI broadcast all types for the ddb_type structure
INPUTS
comm=MPI communicator
SIDE EFFECTS
Ddb<type(ddb_type)>= Input if node is master, other nodes returns with a completely initialized instance.
SOURCE
1249 subroutine ddb_bcast(ddb, comm) 1250 1251 !Arguments ------------------------------- 1252 !array 1253 class(ddb_type),intent(inout) :: ddb 1254 integer, intent(in) :: comm 1255 1256 !Local variables------------------------------- 1257 !scalars 1258 integer, parameter :: master=0 1259 integer :: ierr 1260 ! ************************************************************************* 1261 1262 if (xmpi_comm_size(comm) == 1) return 1263 1264 DBG_ENTER("COLL") 1265 1266 ! Transmit dimensions and static variables. 1267 call xmpi_bcast(ddb%nblok, master, comm, ierr) 1268 call xmpi_bcast(ddb%natom, master, comm, ierr) 1269 call xmpi_bcast(ddb%ntypat, master, comm, ierr) 1270 call xmpi_bcast(ddb%nsppol, master, comm, ierr) 1271 call xmpi_bcast(ddb%mpert, master, comm, ierr) 1272 call xmpi_bcast(ddb%msize, master, comm, ierr) 1273 1274 call xmpi_bcast(ddb%occopt, master, comm, ierr) 1275 call xmpi_bcast(ddb%prtvol, master, comm, ierr) 1276 1277 !real 1278 call xmpi_bcast(ddb%rprim, master, comm, ierr) 1279 call xmpi_bcast(ddb%gprim, master, comm, ierr) 1280 call xmpi_bcast(ddb%acell, master, comm, ierr) 1281 1282 ! Allocate arrays on the other nodes. 1283 if (xmpi_comm_rank(comm) /= master) then 1284 call ddb%malloc(ddb%msize, ddb%nblok, ddb%natom, ddb%ntypat, ddb%mpert) 1285 end if 1286 1287 call xmpi_bcast(ddb%flg, master, comm, ierr) 1288 call xmpi_bcast(ddb%typ, master, comm, ierr) 1289 call xmpi_bcast(ddb%amu, master, comm, ierr) 1290 call xmpi_bcast(ddb%nrm, master, comm, ierr) 1291 call xmpi_bcast(ddb%qpt, master, comm, ierr) 1292 call xmpi_bcast(ddb%val, master, comm, ierr) 1293 1294 DBG_EXIT("COLL") 1295 1296 end subroutine ddb_bcast
m_ddb/ddb_can_merge_blocks [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_can_merge_blocks
FUNCTION
Return true if iblok1 of ddb1 can be merged to iblok2 of ddb2
INPUTS
ddb1=ddb object 1 ddb2=ddb object 2 iblok1=block index from ddb1 iblok2=block index from ddb2
OUTPUT
can_merge=.true. if the blocks are compatible for merging.
SOURCE
2801 logical function ddb_can_merge_blocks(ddb1, ddb2, iblok1, iblok2) result(can_merge) 2802 2803 !Arguments ------------------------------- 2804 !array 2805 class(ddb_type),intent(inout) :: ddb1 2806 type(ddb_type),intent(inout) :: ddb2 2807 integer,intent(in) :: iblok1 2808 integer,intent(in) :: iblok2 2809 2810 !local variables 2811 !scalars 2812 integer :: nq, ii, blktyp 2813 real(dp),parameter :: qtol=2.0d-8 2814 real(dp) :: diff 2815 2816 ! ************************************************************************ 2817 2818 can_merge = .false. 2819 if(ddb1%typ(iblok1)/=ddb2%typ(iblok2)) return 2820 2821 blktyp = ddb1%typ(iblok1) 2822 2823 can_merge = .true. 2824 2825 if (is_type_d0E(blktyp) .or. is_type_d1E(blktyp)) return 2826 2827 ! Compare wavevectors 2828 if (is_type_d2E(blktyp).or.is_type_d2eig(blktyp))then 2829 nq=1 2830 else if (is_type_d3E(blktyp))then 2831 nq=3 2832 end if 2833 2834 do ii=1,nq 2835 diff = (ddb1%qpt(1+3*(ii-1),iblok1)/ddb1%nrm(ii,iblok1) & 2836 - ddb2%qpt(1+3*(ii-1),iblok2)/ddb2%nrm(ii,iblok2)) 2837 if (abs(diff) > qtol) can_merge = .false. 2838 diff = (ddb1%qpt(2+3*(ii-1),iblok1)/ddb1%nrm(ii,iblok1) & 2839 - ddb2%qpt(2+3*(ii-1),iblok2)/ddb2%nrm(ii,iblok2)) 2840 if (abs(diff) > qtol) can_merge = .false. 2841 diff = (ddb1%qpt(3+3*(ii-1),iblok1)/ddb1%nrm(ii,iblok1) & 2842 - ddb2%qpt(3+3*(ii-1),iblok2)/ddb2%nrm(ii,iblok2)) 2843 if (abs(diff) > qtol) can_merge = .false. 2844 end do 2845 2846 end function ddb_can_merge_blocks
m_ddb/ddb_copy [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_copy
FUNCTION
Create object and copy all types for the ddb_type structure
SOURCE
578 subroutine ddb_copy(iddb, oddb) 579 580 !Arguments ------------------------------- 581 !array 582 class(ddb_type),intent(in) :: iddb 583 type(ddb_type),intent(out) :: oddb 584 585 ! ************************************************************************ 586 587 ! Copy dimensions and static variables. 588 oddb%msize = iddb%msize 589 oddb%mpert = iddb%mpert 590 oddb%nblok = iddb%nblok 591 oddb%natom = iddb%natom 592 oddb%ntypat = iddb%ntypat 593 oddb%occopt = iddb%occopt 594 oddb%prtvol = iddb%prtvol 595 596 oddb%rprim = iddb%rprim 597 oddb%gprim = iddb%gprim 598 oddb%acell = iddb%acell 599 600 ! Allocate and copy the allocatable arrays. 601 call alloc_copy(iddb%flg, oddb%flg) 602 call alloc_copy(iddb%typ, oddb%typ) 603 call alloc_copy(iddb%amu, oddb%amu) 604 call alloc_copy(iddb%nrm, oddb%nrm) 605 call alloc_copy(iddb%qpt, oddb%qpt) 606 call alloc_copy(iddb%val, oddb%val) 607 608 end subroutine ddb_copy
m_ddb/ddb_diagoq [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_diagoq
FUNCTION
Compute the phonon frequencies at the specified q-point by performing a direct diagonalization of the dynamical matrix. The q-point **MUST** be one the points stored in the DDB file.
INPUTS
ddb<type(ddb_type)>=Object storing the DDB results. crystal<type(crystal_t)> = Information on the crystalline structure. asrq0<asrq0_t>=Object for the treatment of the ASR based on the q=0 block found in the DDB file. symdynmat=If equal to 1, the dynamical matrix is symmetrized in dfpt_phfrq before the diagonalization. rftyp = 1 if non-stationary block 2 if stationary block 3 if third order derivatives qpt(3)=q-point in reduced coordinates.
OUTPUT
phfrq(3*crystal%natom)=Phonon frequencies in Hartree displ_cart(2,3*%natom,3*%natom)=Phonon displacement in Cartesian coordinates [out_eigvec(2*3*natom*3*natom) = The igenvectors of the dynamical matrix. [out_displ_red(2*3*natom*3*natom) = The displacement in reduced coordinates.
SOURCE
4399 subroutine ddb_diagoq(ddb, crystal, qpt, asrq0, symdynmat, rftyp, phfrq, displ_cart, & 4400 out_eigvec,out_displ_red) ! Optional [out] 4401 4402 !Arguments ------------------------------- 4403 !scalars 4404 integer,intent(in) :: symdynmat 4405 integer,intent(in) :: rftyp 4406 class(ddb_type),intent(in) :: ddb 4407 type(asrq0_t),intent(inout) :: asrq0 4408 type(crystal_t),intent(in) :: crystal 4409 !arrays 4410 real(dp),intent(in) :: qpt(3) 4411 real(dp),intent(out) :: displ_cart(2,3,crystal%natom,3,crystal%natom) 4412 real(dp),intent(out) :: phfrq(3*crystal%natom) 4413 !real(dp),optional,intent(out) :: out_d2cart(2,3*crystal%natom,3*crystal%natom) 4414 real(dp),optional,intent(out) :: out_eigvec(2,3,crystal%natom,3*crystal%natom) 4415 real(dp),optional,intent(out) :: out_displ_red(2,3,crystal%natom,3*crystal%natom) 4416 4417 !Local variables------------------------------- 4418 integer :: iblok,natom 4419 !arrays 4420 integer :: rfphon(4),rfelfd(4),rfstrs(4) 4421 real(dp) :: qphnrm(3), qphon_padded(3,3),d2cart(2,ddb%msize),my_qpt(3) 4422 real(dp) :: eigvec(2,3,crystal%natom,3*crystal%natom),eigval(3*crystal%natom) 4423 4424 ! ************************************************************************ 4425 4426 ! Use my_qpt because dfpt_phfrq can change the q-point (very bad design) 4427 qphnrm = one; my_qpt = qpt 4428 4429 ! Look for the information in the DDB (no interpolation here!) 4430 rfphon(1:2)=1; rfelfd(1:2)=0; rfstrs(1:2)=0 4431 qphon_padded = zero; qphon_padded(:,1) = qpt 4432 natom = crystal%natom 4433 4434 call ddb%get_block(iblok, qphon_padded, qphnrm, rfphon, rfelfd, rfstrs, rftyp) 4435 ABI_CHECK(iblok /= 0, sjoin("Cannot find q-point ", ktoa(qpt)," in DDB file")) 4436 4437 ! Copy the dynamical matrix in d2cart 4438 d2cart(:,1:ddb%msize) = ddb%val(:,:,iblok) 4439 4440 ! Eventually impose the acoustic sum rule based on previously calculated d2asr 4441 call asrq0%apply(natom, ddb%mpert, ddb%msize, crystal%xcart, d2cart) 4442 4443 ! Calculation of the eigenvectors and eigenvalues of the dynamical matrix 4444 call dfpt_phfrq(ddb%amu,displ_cart,d2cart,eigval,eigvec,crystal%indsym,& 4445 ddb%mpert,crystal%nsym,natom,crystal%nsym,crystal%ntypat,phfrq,qphnrm(1),my_qpt,& 4446 crystal%rprimd,symdynmat,crystal%symrel,crystal%symafm,crystal%typat,crystal%ucvol) 4447 4448 ! Return the dynamical matrix and the eigenvector for this q-point 4449 !if (present(out_d2cart)) out_d2cart = d2cart(:,:3*natom,:3*natom) 4450 if (present(out_eigvec)) out_eigvec = eigvec 4451 4452 ! Return phonon displacement in reduced coordinates. 4453 if (present(out_displ_red)) call phdispl_cart2red(natom, crystal%gprimd, displ_cart, out_displ_red) 4454 4455 end subroutine ddb_diagoq
m_ddb/ddb_free [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_free
FUNCTION
Clean and deallocate types for the ddb_type structure
SOURCE
545 subroutine ddb_free(ddb) 546 547 !Arguments ------------------------------- 548 class(ddb_type),intent(inout) :: ddb 549 550 ! ************************************************************************ 551 552 !integer 553 ABI_SFREE(ddb%flg) 554 ABI_SFREE(ddb%typ) 555 556 ! real 557 ABI_SFREE(ddb%amu) 558 ABI_SFREE(ddb%qpt) 559 ABI_SFREE(ddb%nrm) 560 ABI_SFREE(ddb%kpt) 561 ABI_SFREE(ddb%val) 562 ABI_SFREE(ddb%eig2dval) 563 564 end subroutine ddb_free
m_ddb/ddb_from_file [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_from_file
FUNCTION
This subroutine reads data from the DDB file and constructs an instance of ddb_type It also returns an instance of crystal_t with the crystalline structure reported in the DDB file and the DDB header.
INPUTS
filename=DDB filename. comm=MPI communicator. [prtvol] = Verbosity level raw = 1 -> do not perform any symetrization or transformation to cartesian coordinates. 0 (default) -> do perform these transformations.
OUTPUT
ddb<type(ddb_type)>=Object storing the DDB results. crystal<type(crystal_t)>=Crystal structure parameters ddb_hdr<type(ddb_hdr_type)>= Header of the DDB file.
SOURCE
2399 subroutine ddb_from_file(ddb, filename, ddb_hdr, crystal, comm, prtvol, raw) 2400 2401 !Arguments ------------------------------- 2402 !scalars 2403 class(ddb_type),intent(inout) :: ddb 2404 integer,intent(in) :: comm 2405 integer,optional,intent(in) :: prtvol, raw 2406 character(len=*),intent(in) :: filename 2407 type(crystal_t),intent(out) :: Crystal 2408 type(ddb_hdr_type),intent(out) :: ddb_hdr 2409 !array 2410 2411 !Local variables------------------------------- 2412 integer :: iomode 2413 character(len=fnlen) :: filename_ 2414 integer :: prtvol_ 2415 character(len=500) :: msg 2416 2417 ! ************************************************************************ 2418 2419 DBG_ENTER("COLL") 2420 2421 prtvol_ = 0; if (present(prtvol)) prtvol_ = prtvol 2422 2423 call ddb_hdr%get_iomode(filename, 1, iomode, filename_) 2424 2425 if (iomode==IO_MODE_ETSF) then 2426 call ddb%read_nc(filename_, ddb_hdr, crystal, comm, prtvol, raw) 2427 else if (iomode==IO_MODE_FORTRAN) then 2428 call ddb%read_txt(filename_, ddb_hdr, crystal, comm, prtvol, raw) 2429 end if 2430 2431 ! Print out info on the crystal 2432 if (prtvol_ >= 0) then 2433 2434 call ddb_hdr%crystal%print(unit=ab_out) 2435 call ddb_hdr%crystal%print(unit=std_out) 2436 2437 write(msg, '(2a,i0,a)' )ch10,' DDB file with ',ddb%nblok,' blocks has been read.' 2438 call wrtout(std_out,msg) 2439 call wrtout(ab_out,msg) 2440 2441 end if 2442 2443 DBG_EXIT("COLL") 2444 2445 end subroutine ddb_from_file
m_ddb/ddb_get_asrq0 [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_asrq0
FUNCTION
In case the interatomic forces are not calculated, the ASR-correction has to be determined here from the Dynamical matrix at Gamma. In case the DDB does not contain this information, the subroutine returns iblok=0 %d2asr is initialized and set to zero to preserve the old behaviour.
INPUTS
asr=Input variable selecting the method for the ASR rftyp = 1 if non-stationary block 2 if stationary block 3 if third order derivatives xcart(3,ddb%atom)=Cartesian coordinates of the atoms.
SIDE EFFECTS
ddb<type(ddb_type)>= Database with the derivates. The routine does not change it except when asr is in [3,4]. TODO This should not happen.
OUTPUT
asrq0<asrq0_t> iblok= is set to 0 if the Gamma block is not found
SOURCE
4106 type(asrq0_t) function ddb_get_asrq0(ddb, asr, rftyp, xcart) result(asrq0) 4107 4108 !Arguments ------------------------------- 4109 !scalars 4110 integer,intent(in) :: asr,rftyp 4111 class(ddb_type),intent(inout) :: ddb 4112 !arrays 4113 real(dp),intent(in) :: xcart(3,ddb%natom) 4114 4115 !Local variables------------------------------- 4116 !scalars 4117 integer :: dims,iblok 4118 !character(len=500) :: msg 4119 !arrays 4120 integer :: rfelfd(4),rfphon(4),rfstrs(4) 4121 real(dp) :: qphnrm(3),qphon(3,3) 4122 real(dp),allocatable :: d2asr_res(:,:,:,:,:),d2cart(:,:) 4123 4124 ! ************************************************************************ 4125 4126 asrq0%asr = asr; asrq0%natom = ddb%natom 4127 4128 ! Find the Gamma block in the DDB (no need for E-field entries) 4129 qphon(:,1)=zero 4130 qphnrm(1)=zero 4131 rfphon(1:2)=1 4132 rfelfd(:)=0 4133 rfstrs(:)=0 4134 4135 call ddb%get_block(asrq0%iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp) 4136 ! this is to maintain the old behaviour in which the arrays where allocated and set to zero in anaddb. 4137 ABI_MALLOC(asrq0%d2asr, (2,3,ddb%natom,3,ddb%natom)) 4138 asrq0%d2asr = zero 4139 4140 if (asrq0%iblok == 0) return 4141 iblok = asrq0%iblok 4142 4143 select case (asrq0%asr) 4144 case (0) 4145 continue 4146 4147 case (1,2) 4148 call asria_calc(asr,asrq0%d2asr,ddb%val(:,:,iblok),ddb%mpert,ddb%natom) 4149 4150 case (3,4) 4151 ! Rotational invariance for 1D and 0D systems 4152 ! Compute uinvers, vtinvers and singular matrices. 4153 dims = 3*ddb%natom*(3*ddb%natom-1) / 2 4154 ABI_CALLOC(asrq0%uinvers, (dims, dims)) 4155 ABI_CALLOC(asrq0%vtinvers,(dims, dims)) 4156 ABI_CALLOC(asrq0%singular, (dims)) 4157 4158 call asrprs(asr,1,3,asrq0%uinvers,asrq0%vtinvers,asrq0%singular,& 4159 ddb%val(:,:,iblok),ddb%mpert,ddb%natom,xcart) 4160 4161 case (5) 4162 ! d2cart is a temp variable here 4163 ABI_MALLOC(d2cart,(2,ddb%msize)) 4164 d2cart = ddb%val(:,:,iblok) 4165 ! calculate diagonal correction 4166 call asria_calc(2,asrq0%d2asr,d2cart,ddb%mpert,ddb%natom) 4167 ! apply diagonal correction 4168 call asria_corr(2,asrq0%d2asr,d2cart,ddb%mpert,ddb%natom) 4169 ! hermitianize 4170 call mkherm(d2cart,3*ddb%mpert) 4171 ! remove remaining ASR rupture due to Hermitianization 4172 ABI_MALLOC(d2asr_res,(2,3,ddb%natom,3,ddb%natom)) 4173 call asria_calc(asr,d2asr_res,d2cart,ddb%mpert,ddb%natom) 4174 ! full correction is sum of both 4175 asrq0%d2asr = asrq0%d2asr + d2asr_res 4176 4177 ABI_FREE(d2cart) 4178 ABI_FREE(d2asr_res) 4179 4180 case default 4181 ABI_ERROR(sjoin("Wrong value for asr:", itoa(asr))) 4182 end select 4183 4184 end function ddb_get_asrq0
m_ddb/ddb_get_block [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_block
FUNCTION
This routine finds the block that contains the information on the derivatives of the total energy specified by the parameters rfphon,rfelfd,rfstrs,rftyp and the phonon wavevectors qphon (and their normalisation). In case the DDB does not contain this information, the subroutine returns iblok=0
INPUTS
ddb = ddb blok datastructure flg(msize,nblok)=flag for every matrix element: 0 => the element is not in the data block. 1 => the element is in the data blok. nrm(3,nblok)=normalization factors for the three allowed wavevectors qpt(3,nblok)=wavevector of the perturbation(s). The elements typ(nblok)=type of the block. (1=> non-stationary block), (2=> stationary block), (3=> third order derivative). qphon(3,3)=wavevectors for the three possible phonons (note : only one should be used in case of second derivative of total energy, because we know that the second is the opposite of this value) qphnrm(3) =normalisation factors for the three possible phonons rfphon(4) = 1=> response to phonons 2=> second derivative of total energy rfelfd(4) = 1=> d/dk, 2=> electric field only, 3=> both (see comment on rfphon) rfstrs(4) = 1=> uniaxial stresses, 2=> shear stresses, 3=> both (see comment on rfphon) rftyp = 0 => total energy 1 => non-stationary formulation of the 2nd derivative 2 => stationary formulation of the 2nd derivative 3 => third derivative of total energy 4 => first-order derivatives of total energy 33 => long wave third order derivatives of total energy 85 => molecular Berry curvature [rfqvec(4)] = 1=> d/dq (optional)
OUTPUT
iblok= number of the block that corresponds to the specifications. 0 if not found.
SOURCE
1347 subroutine ddb_get_block(ddb, iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, rfqvec) 1348 1349 !Arguments ------------------------------- 1350 !scalars 1351 integer,intent(in) :: rftyp 1352 integer,intent(out) :: iblok 1353 class(ddb_type),intent(in) :: ddb 1354 !arrays 1355 integer,intent(in) :: rfelfd(4),rfphon(4),rfstrs(4) 1356 real(dp),intent(inout) :: qphnrm(3),qphon(3,3) 1357 integer,optional,intent(in) :: rfqvec(4) 1358 1359 !Local variables ------------------------- 1360 !scalars 1361 integer :: blkgam,ider,idir,idir1,idir2,idir3,ii,index,ipert,ipert1,ipert2 1362 integer :: ipert3,nder,ok,mpert,natom 1363 character(len=500) :: msg 1364 !arrays 1365 integer :: gamma(3) 1366 integer,allocatable :: worki(:,:) 1367 real(dp) :: qpt(3) 1368 integer :: rfqvec_(4) 1369 1370 ! ********************************************************************* 1371 1372 mpert = ddb%mpert 1373 natom = ddb%natom 1374 1375 ! Get the number of derivative 1376 if (is_type_d2E(rftyp)) then 1377 nder=2 1378 else if (is_type_d3E(rftyp)) then 1379 nder=3 1380 else if (is_type_d0E(rftyp)) then 1381 nder=0 1382 else if (is_type_d1E(rftyp)) then 1383 nder=1 1384 else 1385 write(msg, '(a,i0,a)')' rftyp is equal to ',rftyp,'. The only allowed values are 0, 1, 2, 3, 5, 6, 33 or 85.' 1386 ABI_BUG(msg) 1387 end if 1388 1389 rfqvec_(:)=0; if(present(rfqvec))rfqvec_(:)=rfqvec(:) 1390 1391 ! In case of a second-derivative, a second phonon wavevector is provided. 1392 if(nder==2)then 1393 do ii=1,3 1394 qphon(ii,2)=-qphon(ii,1) 1395 end do 1396 qphnrm(2)=qphnrm(1) 1397 end if 1398 1399 ! In case of a third derivative, the sum of wavevectors to gamma is checked 1400 if (nder == 3) then 1401 qpt(:) = qphon(:,1)/qphnrm(1) + qphon(:,2)/qphnrm(2) + qphon(:,3)/qphnrm(3) 1402 call gamma9(gamma(nder),qpt,qphnrm(1),DDB_QTOL) 1403 if (gamma(nder) == 0) then 1404 write(msg,'(a,a,a)')& 1405 'the sum of the wavevectors of the third-order energy is ',ch10,& 1406 'not equal to zero' 1407 ABI_ERROR(msg) 1408 end if 1409 end if 1410 1411 ! Check the validity of the requirement 1412 do ider=1,nder 1413 ! Identifies if qphon is at gamma 1414 call gamma9(gamma(ider),qphon(1:3,ider),qphnrm(ider),DDB_QTOL) 1415 1416 if(gamma(ider)==0)then 1417 if(rfstrs(ider)/=0.or.rfelfd(ider)/=0.or.rfqvec_(ider)/=0)then 1418 write(msg, '(a,a)' )& 1419 'Not yet able to handle stresses or electric fields',ch10,& 1420 'with non-zero wavevector.' 1421 ABI_BUG(msg) 1422 end if 1423 end if 1424 end do 1425 1426 ! Initialise the perturbation table 1427 ABI_MALLOC(worki,(mpert,4)) 1428 worki(:,1:nder)=0 1429 1430 ! Build the perturbation table 1431 do ider=1,nder 1432 ! First the phonons 1433 if(rfphon(ider)==1)then ! what about the rfphon = 2 case ? 1434 do ipert=1,natom 1435 worki(ipert,ider)=1 1436 end do 1437 end if 1438 ! Then the d/dk 1439 if (rfelfd(ider)==1.or.rfelfd(ider)==3) worki(natom+1,ider)=1 1440 ! Then the electric field 1441 if (rfelfd(ider)==2.or.rfelfd(ider)==3) worki(natom+2,ider)=1 1442 ! Then the ddq 1443 if (rfqvec_(ider)==1) worki(natom+8,ider)=1 1444 ! Then the uniaxial stress 1445 if (rfstrs(ider)==1.or.rfstrs(ider)==3) worki(natom+3,ider)=1 1446 ! At last, the shear stress 1447 if(rfstrs(ider)==2.or.rfstrs(ider)==3) worki(natom+4,ider)=1 1448 end do 1449 1450 ! Examine every blok: 1451 do iblok=1,ddb%nblok 1452 1453 ! If this variable is still 1 at the end of the examination, the blok is the good one... 1454 ok=1 1455 1456 ! Check the type 1457 if(rftyp/=ddb%typ(iblok)) ok=0 1458 1459 ! Check the wavevector 1460 if( ok==1 )then 1461 1462 if (nder == 2) then 1463 call gamma9(blkgam,ddb%qpt(1:3,iblok),ddb%nrm(1,iblok),DDB_QTOL) 1464 if(blkgam/=gamma(1))then 1465 ok=0 1466 else if(blkgam==0)then 1467 do idir=1,3 1468 if( abs( ddb%qpt(idir,iblok)/ddb%nrm(1,iblok) - qphon(idir,1)/qphnrm(1) )>DDB_QTOL ) ok=0 1469 end do 1470 end if 1471 1472 else if (nder == 3) then 1473 do ider = 1, nder 1474 do idir=1,3 1475 if( abs( ddb%qpt(idir+3*(ider-1),iblok)/ddb%nrm(ider,iblok) - qphon(idir,ider)/qphnrm(ider) )>DDB_QTOL )then 1476 ok=0 1477 end if ! qphon 1478 end do ! idir 1479 end do ! nder 1480 end if ! nder 1481 1482 end if ! ok 1483 1484 ! Check if there is enough information in this blok 1485 if( ok==1 )then 1486 1487 if (nder == 0) then 1488 if (ddb%flg(1,iblok) /= 1) then 1489 ok = 0 1490 if (ddb%prtvol > 1) then 1491 write(msg,'(a,i0,3a)' )& 1492 'The block ',iblok,' does not match the requirement',ch10,& 1493 'because it lacks the total energy' 1494 ABI_COMMENT(msg) 1495 end if 1496 end if 1497 end if 1498 1499 do ipert1=1,mpert 1500 1501 if ((nder == 4).and.(worki(ipert1,4) == 1).and.(ok == 1)) then 1502 do idir1 = 1, 3 1503 index = 3*(ipert1 - 1) + idir1 1504 if (ddb%flg(index,iblok) /= 1) ok = 0 1505 end do 1506 end if 1507 1508 if (worki(ipert1,1)==1 .and. ok==1 )then 1509 do ipert2=1,mpert 1510 if (worki(ipert2,2)==1 .and. ok==1 )then 1511 do idir1=1,3 1512 do idir2=1,3 1513 1514 if (nder == 2) then 1515 index=idir1+ 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1))) 1516 if (ddb%flg(index,iblok)/=1) ok=0 1517 1518 else if (nder == 3) then 1519 do ipert3 = 1, mpert 1520 if (worki(ipert3,3) == 1 .and. ok == 1) then 1521 do idir3 = 1, 3 1522 index = idir1 + & 1523 3*((ipert1 - 1) + mpert*((idir2 - 1) + & 1524 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1))))) 1525 if (ddb%flg(index,iblok) /= 1) ok = 0 1526 end do ! idir3 1527 end if ! worki(ipert3,3) 1528 end do ! i3pert 1529 end if 1530 1531 end do 1532 end do 1533 end if 1534 end do 1535 end if 1536 end do 1537 end if 1538 1539 ! Now that everything has been checked, eventually end the search 1540 if(ok==1)exit 1541 end do 1542 1543 if(ok==0)then 1544 iblok=0 1545 1546 if (ddb%prtvol > 1) then 1547 write(msg, '(3a)' )& 1548 ' gtblk9 : ',ch10,& 1549 ' Unable to find block corresponding to the following specifications :' 1550 call wrtout(std_out,msg) 1551 write(msg, '(a,i3)' )' Type (rfmeth) =',rftyp 1552 call wrtout(std_out,msg) 1553 write(msg, '(a)' ) ' ider qphon(3) qphnrm rfphon rfelfd rfstrs rfqvec' 1554 call wrtout(std_out,msg) 1555 do ider=1,nder 1556 write(msg, '(i4,4f6.2,4i7)' )& 1557 ider,(qphon(ii,ider),ii=1,3),qphnrm(ider),rfphon(ider),rfelfd(ider),rfstrs(ider),rfqvec_(ider) 1558 call wrtout(std_out,msg) 1559 end do 1560 end if 1561 end if 1562 1563 if (ok==1 .and. ddb%prtvol > 1) then 1564 write(msg,'(a,i0,2a)')' gtblk9: found block number ',iblok,' agree with',' specifications ' 1565 call wrtout(std_out,msg) 1566 end if 1567 1568 ABI_FREE(worki) 1569 1570 end subroutine ddb_get_block
m_ddb/ddb_get_d1matr [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_d1matr
FUNCTION
Transform the first-order derivative matrix from flat indices to real tensor d1matr(cplex,ncart,natom)
INPUTS
iblok=index of the block to get.
OUTPUT
d1matr=the first-order derivative matrix. flg=flag to indicate presence of a given element.
SOURCE
1023 subroutine ddb_get_d1matr(ddb, iblok, d1matr, flg) 1024 1025 !Arguments ------------------------------- 1026 !array 1027 class(ddb_type),intent(inout) :: ddb 1028 integer,intent(in) :: iblok 1029 real(dp), allocatable, intent(out) :: d1matr(:,:,:) 1030 integer, allocatable, intent(out) :: flg(:,:) 1031 !scalars 1032 1033 !Local variables ------------------------- 1034 !scalars 1035 integer :: ii,idir1,ipert1 1036 1037 ! ************************************************************************ 1038 1039 ABI_MALLOC(d1matr, (2,3,ddb%mpert)) 1040 ABI_MALLOC(flg, (3,ddb%mpert)) 1041 1042 d1matr = zero 1043 1044 ii=0 1045 do ipert1=1,ddb%mpert 1046 do idir1=1,3 1047 ii=ii+1 1048 flg(idir1,ipert1) = ddb%flg(ii,iblok) 1049 if (ddb%flg(ii,iblok) > 0) then 1050 d1matr(1,idir1,ipert1) = ddb%val(1,ii,iblok) 1051 d1matr(2,idir1,ipert1) = ddb%val(2,ii,iblok) 1052 end if 1053 end do 1054 end do 1055 1056 end subroutine ddb_get_d1matr
m_ddb/ddb_get_d2eig [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_d2eig
FUNCTION
Transform the second-order derivative matrix of eigenvalues from flat indices to real tensor d2eig(cplex,ncart,natom,ncart,natom,nband,nkpt)
INPUTS
iblok=index of the block to get. OUTPUTS d2eig(cplex,ncart,natom,ncart,natom,nband,nkpt) = the second-order derivative matrix of eigenvalues with the isppol index wrapped in nband. flg(ncart,natom,ncart,natom)=flag to indicate presence of a given element.
SOURCE
5820 subroutine ddb_get_d2eig(ddb, d2eig, flg, iblok) 5821 5822 !Arguments ------------------------------- 5823 !array 5824 class(ddb_type),intent(inout) :: ddb 5825 real(dp), allocatable, intent(out) :: d2eig(:,:,:,:,:,:,:) 5826 integer,intent(in) :: iblok 5827 integer, allocatable, intent(out) :: flg(:,:,:,:) 5828 !scalars 5829 5830 !Local variables ------------------------- 5831 !scalars 5832 integer :: ii,idir1,idir2,ipert1,ipert2,iband,ikpt 5833 5834 ! ************************************************************************ 5835 5836 ABI_MALLOC(d2eig, (2,3,ddb%mpert,3,ddb%mpert,ddb%nband,ddb%nkpt)) 5837 ABI_MALLOC(flg, (3,ddb%mpert,3,ddb%mpert)) 5838 5839 d2eig = zero 5840 5841 do ikpt=1,ddb%nkpt 5842 do iband=1,ddb%nband 5843 ii=0 5844 do ipert2=1,ddb%mpert 5845 do idir2=1,3 5846 do ipert1=1,ddb%mpert 5847 do idir1=1,3 5848 ii=ii+1 5849 flg(idir1,ipert1,idir2,ipert2) = ddb%flg(ii,iblok) 5850 if (ddb%flg(ii,iblok) > 0) then 5851 d2eig(1,idir1,ipert1,idir2,ipert2,iband,ikpt) = ddb%eig2dval(1,ii,iband,ikpt) 5852 d2eig(2,idir1,ipert1,idir2,ipert2,iband,ikpt) = ddb%eig2dval(2,ii,iband,ikpt) 5853 end if 5854 end do 5855 end do 5856 end do 5857 end do 5858 end do 5859 end do 5860 5861 end subroutine ddb_get_d2eig
m_ddb/ddb_get_d2matr [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_d2matr
FUNCTION
Transform the second-order derivative matrix from flat indices to real tensor d2matr(cplex,ncart,natom,ncart,natom)
INPUTS
iblok=index of the block to get.
OUTPUT
d2matr=the second-order derivative matrix. flg=flag to indicate presence of a given element.
SOURCE
829 subroutine ddb_get_d2matr(ddb, iblok, d2matr, flg) 830 831 !Arguments ------------------------------- 832 !array 833 class(ddb_type),intent(inout) :: ddb 834 integer,intent(in) :: iblok 835 real(dp), allocatable, intent(out) :: d2matr(:,:,:,:,:) 836 integer, allocatable, intent(out) :: flg(:,:,:,:) 837 !scalars 838 839 !Local variables ------------------------- 840 !scalars 841 integer :: ii,idir1,idir2,ipert1,ipert2 842 843 ! ************************************************************************ 844 845 ABI_MALLOC(d2matr, (2,3,ddb%mpert,3,ddb%mpert)) 846 ABI_MALLOC(flg, (3,ddb%mpert,3,ddb%mpert)) 847 848 d2matr = zero 849 850 ii=0 851 do ipert2=1,ddb%mpert 852 do idir2=1,3 853 do ipert1=1,ddb%mpert 854 do idir1=1,3 855 ii=ii+1 856 flg(idir1,ipert1,idir2,ipert2) = ddb%flg(ii,iblok) 857 if (ddb%flg(ii,iblok) > 0) then 858 d2matr(1,idir1,ipert1,idir2,ipert2) = ddb%val(1,ii,iblok) 859 d2matr(2,idir1,ipert1,idir2,ipert2) = ddb%val(2,ii,iblok) 860 end if 861 end do 862 end do 863 end do 864 end do 865 866 end subroutine ddb_get_d2matr
m_ddb/ddb_get_d3matr [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_d3matr
FUNCTION
Transform the third-order derivative matrix from flat indices to real tensor d3matr(cplex,ncart,natom,ncart,natom,ncart,natom)
INPUTS
iblok=index of the block to get.
OUTPUT
d3matr=the third-order derivative matrix. flg=flag to indicate presence of a given element.
SOURCE
5755 subroutine ddb_get_d3matr(ddb, iblok, d3matr, flg) 5756 5757 !Arguments ------------------------------- 5758 !array 5759 class(ddb_type),intent(inout) :: ddb 5760 integer,intent(in) :: iblok 5761 real(dp), allocatable, intent(out) :: d3matr(:,:,:,:,:,:,:) 5762 integer, allocatable, intent(out) :: flg(:,:,:,:,:,:) 5763 !scalars 5764 5765 !Local variables ------------------------- 5766 !scalars 5767 integer :: ii,idir1,idir2,idir3,ipert1,ipert2,ipert3 5768 5769 ! ************************************************************************ 5770 5771 ABI_MALLOC(d3matr, (2,3,ddb%mpert,3,ddb%mpert,3,ddb%mpert)) 5772 ABI_MALLOC(flg, (3,ddb%mpert,3,ddb%mpert,3,ddb%mpert)) 5773 5774 d3matr = zero 5775 5776 ii=0 5777 do ipert3=1,ddb%mpert 5778 do idir3=1,3 5779 do ipert2=1,ddb%mpert 5780 do idir2=1,3 5781 do ipert1=1,ddb%mpert 5782 do idir1=1,3 5783 ii=ii+1 5784 flg(idir1,ipert1,idir2,ipert2,idir3,ipert3) = ddb%flg(ii,iblok) 5785 if (ddb%flg(ii,iblok) > 0) then 5786 d3matr(1,idir1,ipert1,idir2,ipert2,idir3,ipert3) = ddb%val(1,ii,iblok) 5787 d3matr(2,idir1,ipert1,idir2,ipert2,idir3,ipert3) = ddb%val(2,ii,iblok) 5788 end if 5789 end do 5790 end do 5791 end do 5792 end do 5793 end do 5794 end do 5795 5796 end subroutine ddb_get_d3matr
m_ddb/ddb_get_dchidet [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_dchidet
FUNCTION
Reads the non-linear optical susceptibility tensor and the first-order change in the linear dielectric susceptibility
INPUTS
ddb<type(ddb_type)>=Derivative Database. ramansr= if /= 0, impose sum rule on first-order derivatives of the electronic susceptibility with respect to atomic displacements nlflag= if =3, only the non-linear optical susceptibilities is computed
OUTPUT
dchide(3,3,3) = non-linear optical coefficients dchidt(natom,3,3,3) = first-order change of the electronic dielectric tensor induced by an individual atomic displacement iblok=Index of the block containing the data. 0 if block is not found. The caller should check the returned value.
SOURCE
3827 integer function ddb_get_dchidet(ddb, ramansr, nlflag, dchide, dchidt) result(iblok) 3828 3829 !Arguments ------------------------------- 3830 !scalars 3831 integer,intent(in) :: ramansr, nlflag 3832 class(ddb_type),intent(in) :: ddb 3833 !arrays 3834 real(dp),intent(out) :: dchide(3,3,3),dchidt(ddb%natom,3,3,3) 3835 3836 !Local variables ------------------------- 3837 !scalars 3838 integer :: rftyp 3839 !arrays 3840 integer :: rfelfd(4),rfphon(4),rfstrs(4) 3841 real(dp) :: qphnrm(3),qphon(3,3) 3842 3843 ! ********************************************************************* 3844 3845 qphon(:,:) = zero 3846 qphnrm(:) = one 3847 ! rfphon(1) = 1 ; rfphon(2:3) = 0 3848 rfelfd(:) = 2 3849 rfstrs(:) = 0 3850 rftyp = BLKTYP_d3E_xx 3851 3852 if (nlflag < 3) then 3853 rfphon(1) = 1 ; rfphon(2:3) = 0 3854 else 3855 rfphon(1) = 0 ; rfphon(2:3) = 0 3856 end if 3857 3858 call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp) 3859 3860 if (iblok /= 0) then 3861 call dtchi(ddb%val(:,:,iblok),dchide,dchidt,ddb%mpert,ddb%natom,ramansr,nlflag) 3862 else 3863 ! Let the caller handle the error. 3864 dchide = huge(one); dchidt = huge(one) 3865 end if 3866 3867 end function ddb_get_dchidet
m_ddb/ddb_get_dielt [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_dielt
FUNCTION
Reads the electronic dielectric tensor from the DDB file
INPUTS
ddb<type(ddb_type)>=Derivative database. rftyp = 1 if non-stationary block 2 if stationary block 3 if third order derivatives
OUTPUT
dielt(3,3) = Macroscopic dielectric tensor (electronic contribution) iblok=Index of the block containing the data. 0 if block is not found.
NOTES
dielt is initialized to one_3D if the derivatives are not available in the DDB file.
SOURCE
3660 integer function ddb_get_dielt(ddb, rftyp, dielt) result(iblok) 3661 3662 !Arguments ------------------------------- 3663 !scalars 3664 integer,intent(in) :: rftyp 3665 class(ddb_type),intent(in) :: ddb 3666 !arrays 3667 real(dp),intent(out) :: dielt(3,3) 3668 3669 !Local variables ------------------------- 3670 !scalars 3671 integer :: mpert 3672 character(len=1000) :: msg 3673 !arrays 3674 integer :: rfelfd(4),rfphon(4),rfstrs(4) 3675 real(dp) :: qphnrm(3),qphon(3,3) 3676 real(dp),allocatable :: tmpval(:,:,:,:) 3677 3678 ! ********************************************************************* 3679 3680 ! Look for the Gamma Block in the DDB 3681 qphon(:,1)=zero 3682 qphnrm(1)=zero 3683 rfphon(1:2)=0 3684 rfelfd(1:2)=2 3685 rfstrs(1:2)=0 3686 3687 call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp) 3688 3689 ! Read the dielectric tensor only if the Gamma-block was found in the DDB 3690 ! In case it was not found, iblok = 0 3691 dielt=zero; dielt(1,1)=one; dielt(2,2)=one; dielt(3,3)=one 3692 3693 if (iblok/=0) then 3694 !Extration of dielectric tensor 3695 mpert = ddb%mpert 3696 3697 ABI_MALLOC(tmpval,(3,mpert,3,mpert)) 3698 tmpval(:,:,:,:) = reshape(ddb%val(1,:,iblok), shape = (/3,mpert,3,mpert/)) 3699 dielt=tmpval(1:3,ddb%natom+2,1:3,ddb%natom+2) 3700 3701 write(msg,'(a,3es16.6,3es16.6,3es16.6)' )& 3702 ' Dielectric Tensor ',& 3703 dielt(1,1),dielt(1,2),dielt(1,3),& 3704 dielt(2,1),dielt(2,2),dielt(2,3),& 3705 dielt(3,1),dielt(3,2),dielt(3,3) 3706 3707 call wrtout(std_out,msg) 3708 3709 ABI_FREE(tmpval) 3710 end if ! iblok not found 3711 3712 end function ddb_get_dielt
m_ddb/ddb_get_dielt_zeff [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_dielt_zeff
FUNCTION
Reads the Dielectric Tensor and the Effective Charges from the DDB file Impose the charge neutrality on the effective charges and eventually select some parts of the effective charges
INPUTS
Crystal<type(crystal_t)>=Crystal structure parameters rftyp = 1 if non-stationary block 2 if stationary block 3 if third order derivatives chneut=(0 => no ASR, 1 => equal repartition,2 => weighted repartition ) selectz=selection of some parts of the effective charge tensor attached to one atom. (0=> no selection, 1=> trace only, 2=> symmetric part only)
SIDE EFFECTS
ddb<type(ddb_type)>= The block with the effective charges is modified if charge neutrality is imposed.
OUTPUT
iblok=Index of the block containing the data. 0 if block is not found. dielt(3,3) = Macroscopic dielectric tensor zeff(3,3,natom)=effective charge on each atom, versus electric field and atomic displacement [zeff_raw(3,3,natom)]=effective charge on each atom before enforcing charge-neutrality.
NOTES
dielt and zeff are initialized to one_3D and zero if the derivatives are not available in the DDB file.
SOURCE
3572 integer function ddb_get_dielt_zeff(ddb, crystal, rftyp, chneut, selectz, dielt, zeff, zeff_raw) result(iblok) 3573 3574 !Arguments ------------------------------- 3575 !scalars 3576 integer,intent(in) :: rftyp,chneut,selectz 3577 class(ddb_type),intent(inout) :: ddb 3578 type(crystal_t),intent(in) :: crystal 3579 !arrays 3580 real(dp),intent(out) :: dielt(3,3),zeff(3,3,crystal%natom) 3581 real(dp),optional,intent(out) :: zeff_raw(3,3,crystal%natom) 3582 3583 !Local variables ------------------------- 3584 !scalars 3585 integer :: ii 3586 character(len=500) :: msg 3587 !arrays 3588 integer :: rfelfd(4),rfphon(4),rfstrs(4) 3589 real(dp) :: qphnrm(3),qphon(3,3), my_zeff_raw(3,3,crystal%natom) 3590 3591 ! ********************************************************************* 3592 3593 ! Look for the Gamma Block in the DDB 3594 qphon(:,1)=zero 3595 qphnrm(1)=zero 3596 rfphon(1:2)=1 3597 rfelfd(1:2)=2 3598 rfstrs(1:2)=0 3599 3600 !write(std_out,*)"ddb%mpert",ddb%mpert 3601 call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp) 3602 3603 ! Compute effective charges and dielectric tensor only if the Gamma-blok was found in the DDB 3604 ! In case it was not found, iblok = 0 3605 zeff=zero; dielt=zero; dielt(1,1)=one; dielt(2,2)=one; dielt(3,3)=one 3606 my_zeff_raw = zero 3607 3608 if (iblok /= 0) then 3609 write(msg, '(2a,(80a),4a)' ) ch10,('=',ii=1,80),ch10,ch10,& 3610 ' Dielectric Tensor and Effective Charges ',ch10 3611 call wrtout([std_out, ab_out], msg) 3612 3613 ! Make the imaginary part of the Gamma block vanish 3614 write(msg, '(5a)' ) ch10,& 3615 ' anaddb : Zero the imaginary part of the Dynamical Matrix at Gamma,',ch10,& 3616 ' and impose the ASR on the effective charges ',ch10 3617 call wrtout([std_out, ab_out], msg) 3618 3619 ! Extrac Zeff before enforcing sum rule. 3620 call dtech9(ddb%val, dielt, iblok, ddb%mpert, ddb%natom, ddb%nblok, my_zeff_raw, unit=dev_null) 3621 3622 ! Impose the charge neutrality on the effective charges and eventually select some parts of the effective charges 3623 call chneu9(chneut,ddb%val(:,:,iblok),ddb%mpert,ddb%natom,ddb%ntypat,selectz,Crystal%typat,Crystal%zion) 3624 3625 ! Extraction of the dielectric tensor and the effective charges 3626 call dtech9(ddb%val, dielt, iblok, ddb%mpert, ddb%natom, ddb%nblok, zeff) 3627 3628 end if ! iblok not found 3629 3630 if (present(zeff_raw)) zeff_raw = my_zeff_raw 3631 3632 end function ddb_get_dielt_zeff
m_ddb/ddb_get_etotal [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_etotal
FUNCTION
Read the GS total energy from the DDB file.
INPUTS
ddb<type(ddb_type)>=Derivative database.
OUTPUT
etotal=GS Total energy in Hartree iblok=Index of the block in the DDB file. 0 if not found.
SOURCE
3502 integer function ddb_get_etotal(ddb, etotal) result(iblok) 3503 3504 !Arguments ------------------------------- 3505 !scalars 3506 real(dp),intent(out) :: etotal 3507 class(ddb_type),intent(in) :: ddb 3508 3509 !Local variables ------------------------- 3510 !scalars 3511 integer :: rftyp 3512 !arrays 3513 integer :: rfelfd(4),rfphon(4),rfstrs(4) 3514 real(dp) :: qphnrm(3),qphon(3,3) 3515 3516 ! ********************************************************************* 3517 3518 ! Extract the block with the total energy 3519 qphon(:,:) = zero 3520 qphnrm(:) = zero 3521 rfphon(:) = 0 3522 rfelfd(:) = 0 3523 rfstrs(:) = 0 3524 rftyp = BLKTYP_d0E_xx 3525 3526 call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp) 3527 3528 if (iblok /= 0) then 3529 etotal = ddb%val(1,1,iblok) 3530 else 3531 etotal = huge(one) 3532 end if 3533 3534 end function ddb_get_etotal
m_ddb/ddb_get_gred [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_gred
FUNCTION
Get the forces in reduced coordinates (Hartree).
INPUTS
ddb<type(ddb_type)>=Derivative database. relaxat 0 => without relaxation of the atoms 1 => with relaxation of the atoms relaxstr 0 => without relaxed lattice constants 1 => with relaxed lattice constants at constrained polarization
OUTPUT
gred(3,natom)=the gradient of the total energy with respect to change of reduced coordinates iblok=Index of the block containing the data. 0 if block is not found.
NOTES
SOURCE
3960 integer function ddb_get_gred(ddb, gred, relaxat, relaxstr) result(iblok) 3961 3962 !Arguments ------------------------------- 3963 !scalars 3964 class(ddb_type),intent(in) :: ddb 3965 integer, intent(in) :: relaxat 3966 integer, intent(in) :: relaxstr 3967 !arrays 3968 real(dp),intent(out),allocatable :: gred(:,:) 3969 3970 !Local variables ------------------------- 3971 !scalars 3972 integer :: natom 3973 integer :: idir, iatom, index 3974 !arrays 3975 integer :: rfelfd(4),rfphon(4),rfstrs(4) 3976 real(dp) :: qphnrm(3),qphon(3,3) 3977 3978 ! ********************************************************************* 3979 3980 natom = ddb%natom 3981 3982 ABI_MALLOC(gred, (3, natom)) 3983 3984 qphon(:,:) = zero; qphnrm(:) = zero 3985 rfphon(:) = 0; rfstrs(:) = 0; rfelfd(:) = 2 3986 if (relaxat == 1) rfphon(:) = 1 3987 if (relaxstr == 1) rfstrs(:) = 3 3988 3989 ! GA: I dont see why relaxstr is relevant as an input 3990 call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, BLKTYP_d1E_xx) 3991 3992 if (iblok/=0) then 3993 if (relaxat == 1) then 3994 index = 0 3995 do iatom = 1, natom 3996 do idir = 1, 3 3997 index = index+1 3998 gred(idir, iatom) = ddb%val(1, index, iblok) 3999 end do 4000 end do 4001 end if 4002 end if 4003 4004 end function ddb_get_gred
m_ddb/ddb_get_pel [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_pel
FUNCTION
Get the electronic polarizability vector from the database.
INPUTS
ddb<type(ddb_type)>=Derivative database. relaxat 0 => without relaxation of the atoms 1 => with relaxation of the atoms relaxstr 0 => without relaxed lattice constants 1 => with relaxed lattice constants at constrained polarization
OUTPUT
pel(3) = Macroscopic polarizability vector (electronic contribution) iblok=Index of the block containing the data. 0 if block is not found.
NOTES
SOURCE
3897 integer function ddb_get_pel(ddb, pel, relaxat, relaxstr) result(iblok) 3898 3899 !Arguments ------------------------------- 3900 !scalars 3901 class(ddb_type),intent(in) :: ddb 3902 integer, intent(in) :: relaxat 3903 integer, intent(in) :: relaxstr 3904 !arrays 3905 real(dp),intent(out) :: pel(3) 3906 3907 !Local variables ------------------------- 3908 !scalars 3909 integer :: natom 3910 !arrays 3911 integer :: rfelfd(4),rfphon(4),rfstrs(4) 3912 real(dp) :: qphnrm(3),qphon(3,3) 3913 3914 ! ********************************************************************* 3915 3916 natom = ddb%natom 3917 3918 qphon(:,:) = zero; qphnrm(:) = zero 3919 rfphon(:) = 0; rfstrs(:) = 0; rfelfd(:) = 2 3920 if (relaxat == 1) rfphon(:) = 1 3921 if (relaxstr == 1) rfstrs(:) = 3 3922 3923 call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, BLKTYP_d1E_xx) 3924 3925 if (iblok/=0) then 3926 pel(1:3) = ddb%val(1, 3*natom+4:3*natom+6, iblok) 3927 end if 3928 3929 end function ddb_get_pel
m_ddb/ddb_get_quadrupoles [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_quadrupoles
FUNCTION
Reads the Dynamic Quadrupoles or the P^(1) tensor from the DDB file
INPUTS
ddb<type(ddb_type)>=Derivative database. ddb_version = 6 digit integer giving date. To mantain compatibility with old DDB files. lwsym = 0 do not symmetrize the tensor wrt efield and qvec derivative |-> 1st gradient of polarization response to atomic displacement = 1 symmetrize the tensor wrt efield and qvec derivative |-> dynamic quadrupoles rftyp = 1 if non-stationary block 2 if stationary block 3 if third order derivatives 33 if long wave third order derivatives
OUTPUT
quadrupoles(3,3,3,natom) = Dynamic Quadrupole tensor iblok=Index of the block containing the data. 0 if block is not found.
NOTES
quadrupoles is initialized to zero if the derivatives are not available in the DDB file.
SOURCE
3746 integer function ddb_get_quadrupoles(ddb, ddb_version, lwsym, rftyp, quadrupoles) result(iblok) 3747 3748 !Arguments ------------------------------- 3749 !scalars 3750 integer,intent(in) :: ddb_version,lwsym,rftyp 3751 class(ddb_type),intent(in) :: ddb 3752 !arrays 3753 real(dp),intent(out) :: quadrupoles(3,3,3,ddb%natom) 3754 3755 !Local variables ------------------------- 3756 !scalars 3757 character(len=500) :: msg 3758 !arrays 3759 integer :: rfelfd(4),rfphon(4),rfstrs(4) 3760 integer :: rfqvec(4) 3761 real(dp) :: qphnrm(3),qphon(3,3) 3762 3763 ! ********************************************************************* 3764 3765 ! Look for the Gamma Block in the DDB 3766 qphon(:,:)=zero 3767 qphnrm(:)=one 3768 rfphon(:)=0 3769 rfelfd(:)=0 3770 rfqvec(:)=0 3771 rfstrs(:)=0 3772 rfelfd(1)=2 3773 rfphon(2)=1 3774 rfqvec(3)=1 3775 3776 call ddb%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,rftyp,rfqvec=rfqvec) 3777 3778 ! Compute the quadrupole tensor only if the Gamma-block was found in the DDB 3779 ! In case it was not found, iblok = 0 3780 quadrupoles=zero 3781 3782 if (iblok /= 0) then 3783 write(msg,'(2a)') ch10, ' Extract quadrupoles or P^(1) coefficients from 3DTE' 3784 call wrtout(std_out, msg) 3785 3786 if (lwsym==1) then 3787 write(msg, '(3a)' ) ch10, ' Dynamical Quadrupoles Tensor (units: e Bohr)',ch10 3788 else if (lwsym==0) then 3789 write(msg, '(3a)' ) ch10, & 3790 ' First moment of Polarization induced by atomic displacement (1/ucvol factor not included) (units: e Bohr) ',ch10 3791 endif 3792 call wrtout([std_out, ab_out], msg) 3793 3794 call dtqdrp(ddb%val(:,:,iblok),ddb_version,lwsym,ddb%mpert,ddb%natom,quadrupoles) 3795 end if 3796 3797 end function ddb_get_quadrupoles
m_ddb/ddb_get_strten [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_get_strten
FUNCTION
Get the stress tensor.
INPUTS
ddb<type(ddb_type)>=Derivative database. relaxat 0 => without relaxation of the atoms 1 => with relaxation of the atoms relaxstr 0 => without relaxed lattice constants 1 => with relaxed lattice constants at constrained polarization
OUTPUT
strten(6)=the stress tensor in cartesian coordinates. iblok=Index of the block containing the data. 0 if block is not found.
NOTES
SOURCE
4034 integer function ddb_get_strten(ddb, strten, relaxat, relaxstr) result(iblok) 4035 4036 !Arguments ------------------------------- 4037 !scalars 4038 class(ddb_type),intent(in) :: ddb 4039 integer, intent(in) :: relaxat 4040 integer, intent(in) :: relaxstr 4041 !arrays 4042 real(dp),intent(out) :: strten(6) 4043 4044 !Local variables ------------------------- 4045 !scalars 4046 integer :: natom 4047 integer :: ii, index 4048 !arrays 4049 integer :: rfelfd(4),rfphon(4),rfstrs(4) 4050 real(dp) :: qphnrm(3),qphon(3,3) 4051 4052 ! ********************************************************************* 4053 4054 natom = ddb%natom 4055 4056 qphon(:,:) = zero; qphnrm(:) = zero 4057 rfphon(:) = 0; rfstrs(:) = 0; rfelfd(:) = 2 4058 if (relaxat == 1) rfphon(:) = 1 4059 if (relaxstr == 1) rfstrs(:) = 3 4060 4061 ! GA: I dont see why relaxstr is relevant as an input 4062 call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, BLKTYP_d1E_xx) 4063 4064 if (iblok/=0) then 4065 if (relaxstr == 1) then 4066 index = 3*natom+6 4067 do ii = 1, 6 4068 index = index+1 4069 strten(ii) = ddb%val(1, index, iblok) 4070 end do 4071 end if 4072 end if 4073 4074 end function ddb_get_strten
m_ddb/ddb_init [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_init
FUNCTION
Initialize a new ddb object for the current calculation.
INPUTS
ddb=the new ddb object dtset=dtset object of the current calculation nblok=number of blocks mpert=maximum number of perturbations (atom displacements + electric field + ...) with_d0E=this ddb contains 0th order derivatives with_d1E=this ddb contains 1st order derivatives with_d2E=this ddb contains 2nd order derivatives with_d3E=this ddb contains 3rd order derivatives with_d2eig=this ddb contains 2nd order derivatives of eigenvalues mband='number of bands' dimension of the d2eig array. Should actually correspond to the maximum number of bands for one kpoint multiplied by the number of spin polarization (mband*nsppol). nkpt=number of kpoints kpt=reduced coordinates of kpoints
SOURCE
447 subroutine ddb_init(ddb, dtset, nblok, mpert, & 448 mband, nkpt, kpt,& 449 with_d0E, with_d1E, with_d2E, with_d3E, with_d2eig) 450 451 !Arguments ------------------------------- 452 class(ddb_type),intent(inout) :: ddb 453 type(dataset_type),intent(in) :: dtset 454 integer,intent(in) :: nblok, mpert 455 integer,intent(in),optional :: mband,nkpt 456 real(dp),intent(in),optional :: kpt(:,:) 457 logical,intent(in),optional :: with_d0E, with_d1E, with_d2E, with_d3E, with_d2eig 458 459 !Local variables ------------------------------- 460 integer :: msize_, ii, ikpt 461 logical :: with_d0E_, with_d1E_, with_d2E_, with_d3E_, with_d2eig_ 462 463 ! ************************************************************************ 464 465 with_d0E_ = .false. ; if (present(with_d0E)) with_d0E_ = with_d0E 466 with_d1E_ = .false. ; if (present(with_d1E)) with_d1E_ = with_d1E 467 with_d2E_ = .false. ; if (present(with_d2E)) with_d2E_ = with_d2E 468 with_d3E_ = .false. ; if (present(with_d3E)) with_d3E_ = with_d3E 469 with_d2eig_ = .false. ; if (present(with_d2eig)) with_d2eig_ = with_d2eig 470 471 msize_ = 0 472 if (with_d0E_) msize_ = 1 473 if (with_d1E_) msize_ = 3 * mpert 474 if (with_d2E_ .or. with_d2eig_) msize_ = 3 * mpert * 3 * mpert 475 if (with_d3E_) msize_ = 3 * mpert * 3 * mpert * 3 * mpert 476 477 call ddb%malloc(msize_, nblok, dtset%natom, dtset%ntypat, mpert) 478 479 ddb%occopt = dtset%occopt 480 ddb%prtvol = dtset%prtvol 481 482 ddb%rprim(:,:) = dtset%rprim_orig(1:3,1:3,1) 483 ddb%acell(:) = dtset%acell_orig(1:3,1) 484 485 call matr3inv(ddb%rprim, ddb%gprim) 486 487 ddb%qpt(:,:) = zero 488 ddb%nrm(:,:) = one 489 if (with_d0E_) then 490 ddb%typ(:) = BLKTYP_d0E_xx 491 else if (with_d1E_) then 492 ddb%typ(:) = BLKTYP_d1E_xx 493 else if (with_d2E_) then 494 ddb%typ(:) = BLKTYP_d2E_ns 495 else if (with_d3E_) then 496 ddb%typ(:) = BLKTYP_d3E_xx 497 else if (with_d2eig_) then 498 ddb%typ(:) = BLKTYP_d2eig_re 499 end if 500 501 ddb%flg(:,:) = 0 502 ddb%amu(:) = dtset%amu_orig(:,1) 503 504 ddb%nsppol = dtset%nsppol 505 506 if (present(mband)) then 507 ddb%nband = mband 508 else 509 ddb%nband = dtset%mband * ddb%nsppol 510 end if 511 512 if (present(nkpt)) then 513 ddb%nkpt = nkpt 514 else 515 ddb%nkpt = dtset%nkpt 516 end if 517 518 ! TODO: Allocate d2eig here instead of leaving it to the calling routine. 519 if (with_d2eig_) then 520 call ddb%malloc_d2eig(ddb%nband, ddb%nkpt) 521 end if 522 523 if (present(kpt)) then 524 do ikpt=1,ddb%nkpt 525 do ii = 1,3 526 ddb%kpt(ii,ikpt) = kpt(ii,ikpt) 527 end do 528 end do 529 end if 530 531 end subroutine ddb_init
m_ddb/ddb_lw_copy [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_lw_copy
FUNCTION
Copy the ddb object after reading the long wave 3rd order derivatives into a new ddb_lw and resizes ddb as for 2nd order derivatives
INPUTS
ddb (INOUT) = ddb block datastructure mpert =maximum number of ipert natom= number of atoms in unit cell ntypat= number of atom types
OUTPUT
ddb_lw= ddb block datastructure
SOURCE
6699 subroutine ddb_lw_copy(ddb,ddb_lw,mpert,natom,ntypat) 6700 6701 !Arguments ------------------------------- 6702 !scalars 6703 integer,intent(in) :: mpert,natom,ntypat 6704 !arrays 6705 type(ddb_type),intent(inout) :: ddb 6706 type(ddb_type),intent(out) :: ddb_lw 6707 6708 !Local variables ------------------------- 6709 !scalars 6710 integer :: ii,nblok,nsize,cnt 6711 6712 ! ********************************************************************* 6713 6714 call ddb%copy(ddb_lw) 6715 call ddb%free() 6716 nsize=3*mpert*3*mpert 6717 nblok=ddb_lw%nblok-count(ddb_lw%typ(:)==BLKTYP_d3E_lw) 6718 call ddb%malloc(nsize, nblok, natom, ntypat, mpert) 6719 6720 ! Copy dimensions and static variables. 6721 ddb%msize = nsize 6722 ddb%mpert = ddb_lw%mpert 6723 ddb%nblok = nblok 6724 ddb%natom = ddb_lw%natom 6725 ddb%ntypat = ddb_lw%ntypat 6726 ddb%occopt = ddb_lw%occopt 6727 ddb%prtvol = ddb_lw%prtvol 6728 6729 ddb%rprim = ddb_lw%rprim 6730 ddb%gprim = ddb_lw%gprim 6731 ddb%acell = ddb_lw%acell 6732 6733 ! Copy the allocatable arrays. 6734 ddb%amu(:) = ddb_lw%amu(:) 6735 cnt = 0 6736 do ii=1,ddb_lw%nblok 6737 if (ddb_lw%typ(ii)/=BLKTYP_d3E_lw) then 6738 cnt = cnt + 1 6739 ddb%flg(:,cnt) = ddb_lw%flg(1:nsize,ii) 6740 ddb%val(:,:,cnt) = ddb_lw%val(:,1:nsize,ii) 6741 ddb%typ(cnt) = ddb_lw%typ(ii) 6742 ddb%nrm(:,cnt) = ddb_lw%nrm(:,ii) 6743 ddb%qpt(:,cnt) = ddb_lw%qpt(:,ii) 6744 end if 6745 end do 6746 6747 end subroutine ddb_lw_copy
m_ddb/ddb_malloc [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_malloc
FUNCTION
Allocate dynamic memory.
INPUTS
msize=maximum size of one block of the ddb (e.g. 3*mpert * 3*mpert) nblok=number of blocks in the ddb natom=number of atoms ntypat=number of atom types mpert=maximum number of perturbations (atom displacements + electric field + ...) nkpt=number of k-points. Optional, indicates the use of eig2d. nband='number of bands' dimension of the d2eig array. Should actually correspond to the maximum number of bands for one kpoint multiplied by the number of spin polarization (mband*nsppol).
OUTPUT
SOURCE
637 subroutine ddb_malloc(ddb, msize, nblok, natom, ntypat, mpert, nkpt, nband) 638 639 !Arguments ------------------------------- 640 !array 641 class(ddb_type),intent(inout) :: ddb 642 integer,intent(in) :: msize,nblok,natom,ntypat,mpert 643 integer,intent(in),optional :: nkpt,nband 644 645 ! ************************************************************************ 646 647 ddb%msize = msize 648 ddb%nblok = nblok 649 ddb%natom = natom 650 !ddb%mpert = natom + MPERT_MAX 651 ddb%mpert = mpert 652 ddb%ntypat = ntypat 653 654 ! integer 655 ABI_CALLOC(ddb%flg, (msize, nblok)) 656 ABI_CALLOC(ddb%typ, (nblok)) 657 658 ! real 659 ABI_MALLOC(ddb%amu, (ntypat)) 660 ABI_MALLOC(ddb%nrm, (3, nblok)) 661 ABI_MALLOC(ddb%qpt, (9, nblok)) 662 ABI_MALLOC(ddb%val, (2, msize, nblok)) 663 ddb%val = huge(one) 664 665 ! FIXME: should really add nsppol argument (see thmeig). 666 if (present(nkpt) .and. present(nband)) then 667 call ddb%malloc_d2eig(nband, nkpt) 668 end if 669 670 end subroutine ddb_malloc
m_ddb/ddb_malloc_d2eig [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_malloc_d2eig
FUNCTION
Allocate dynamic memory for second derivatives of eigenvalues.
INPUTS
mband='number of bands' dimension of the d2eig array. Should actually correspond to the maximum number of bands for one kpoint multiplied by the number of spin polarization (mband*nsppol). nkpt=number of kpoints
OUTPUT
SOURCE
692 subroutine ddb_malloc_d2eig(ddb, mband, nkpt) 693 694 !Arguments ------------------------------- 695 !array 696 class(ddb_type),intent(inout) :: ddb 697 integer,intent(in) :: mband, nkpt 698 699 ! ************************************************************************ 700 701 ddb%nband = mband / ddb%nsppol 702 ddb%nkpt = nkpt 703 ABI_MALLOC(ddb%kpt, (3, nkpt)) 704 ABI_MALLOC(ddb%eig2dval, (2, ddb%msize, mband, nkpt)) 705 706 end subroutine ddb_malloc_d2eig
m_ddb/ddb_merge_blocks [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_merge_blocks
FUNCTION
Merge block number iblok2 from ddb2 into block number iblok1 in ddb1.
INPUTS
ddb1=ddb object 1 ddb2=ddb object 2 iblok1=block index from ddb1 iblok2=block index from ddb2
OUTPUT
SOURCE
2868 subroutine ddb_merge_blocks(ddb1, ddb2, iblok1, iblok2) 2869 2870 !Arguments ------------------------------- 2871 !array 2872 class(ddb_type),intent(inout) :: ddb1 2873 type(ddb_type),intent(inout) :: ddb2 2874 integer,intent(in) :: iblok1 2875 integer,intent(in) :: iblok2 2876 2877 !local variables 2878 !scalars 2879 integer :: ii, blktyp, mpert1, mpert2 2880 integer :: idir1, idir2, idir3, ipert1, ipert2, ipert3 2881 real(dp),parameter :: qtol=2.0d-8 2882 !arrays 2883 real(dp), allocatable :: d1matr(:,:,:) 2884 real(dp), allocatable :: d2matr(:,:,:,:,:) 2885 real(dp), allocatable :: d3matr(:,:,:,:,:,:,:) 2886 integer, allocatable :: d1flg(:,:) 2887 integer, allocatable :: d2flg(:,:,:,:) 2888 integer, allocatable :: d3flg(:,:,:,:,:,:) 2889 2890 ! ************************************************************************ 2891 2892 ! Note that ddb and ddb2 may have a different values for mpert 2893 !mpert = min(ddb1%mpert, ddb2%mpert) 2894 mpert1 = ddb1%mpert 2895 mpert2 = ddb2%mpert 2896 2897 ! Add the blok to the output ddb 2898 blktyp = ddb2%typ(iblok2) 2899 ddb1%typ(iblok1) = blktyp 2900 2901 ! Copy q-point 2902 do ii=1,9 2903 ddb1%qpt(ii,iblok1) = ddb2%qpt(ii,iblok2) 2904 end do 2905 do ii=1,3 2906 ddb1%nrm(ii,iblok1) = ddb2%nrm(ii,iblok2) 2907 end do 2908 2909 if (is_type_d0E(blktyp)) then 2910 ! -------------- 2911 ! Copy d0E block 2912 ! -------------- 2913 if (ddb2%flg(1,iblok2) > 0) then 2914 ddb1%val(1,1,iblok1) = ddb2%val(1,1,iblok2) 2915 ddb1%val(2,1,iblok1) = ddb2%val(2,1,iblok2) 2916 ddb1%flg(1,iblok1) = ddb2%flg(1,iblok2) 2917 end if 2918 2919 else if (is_type_d1E(blktyp)) then 2920 ! -------------- 2921 ! Copy d1E block 2922 ! -------------- 2923 call ddb2%get_d1matr(iblok2, d1matr, d1flg) 2924 !call ddb%set_d1matr(iblok, d1matr, d1flg) 2925 ii=0 2926 do ipert1=1,mpert1 2927 do idir1=1,3 2928 ii=ii+1 2929 if (ipert1 <= mpert2) then 2930 if (d1flg(idir1,ipert1)>0) then 2931 ddb1%val(1,ii,iblok1) = d1matr(1,idir1,ipert1) 2932 ddb1%val(2,ii,iblok1) = d1matr(2,idir1,ipert1) 2933 ddb1%flg(ii,iblok1) = d1flg(idir1,ipert1) 2934 end if 2935 end if 2936 end do 2937 end do 2938 ABI_SFREE(d1matr) 2939 ABI_SFREE(d1flg) 2940 2941 else if (is_type_d2E(blktyp)) then 2942 ! -------------- 2943 ! Copy d2E block 2944 ! -------------- 2945 call ddb2%get_d2matr(iblok2, d2matr, d2flg) 2946 !call ddb%set_d2matr(iblok, d2matr, d2flg) 2947 ii=0 2948 do ipert2=1,mpert1 2949 do idir2=1,3 2950 do ipert1=1,mpert1 2951 do idir1=1,3 2952 ii=ii+1 2953 if ((ipert1 <= mpert2).and.(ipert2<=mpert2)) then 2954 if (d2flg(idir1,ipert1,idir2,ipert2)>0) then 2955 ddb1%val(1,ii,iblok1) = d2matr(1,idir1,ipert1,idir2,ipert2) 2956 ddb1%val(2,ii,iblok1) = d2matr(2,idir1,ipert1,idir2,ipert2) 2957 ddb1%flg(ii,iblok1) = d2flg(idir1,ipert1,idir2,ipert2) 2958 end if 2959 end if 2960 end do 2961 end do 2962 end do 2963 end do 2964 ABI_SFREE(d2matr) 2965 ABI_SFREE(d2flg) 2966 2967 else if (is_type_d3E(blktyp)) then 2968 ! -------------- 2969 ! Copy d3E block 2970 ! -------------- 2971 call ddb2%get_d3matr(iblok2, d3matr, d3flg) 2972 !call ddb%set_d3matr(iblok, d3matr, d3flg) 2973 ii=0 2974 do ipert1=1,mpert1 2975 do idir1=1,3 2976 do ipert2=1,mpert1 2977 do idir2=1,3 2978 do ipert3=1,mpert1 2979 do idir3=1,3 2980 2981 2982 !ii=ii+1 ! GA: This is not equivalent 2983 ii = idir1 + 3*((ipert1-1)+mpert1*((idir2-1) & 2984 + 3*((ipert2-1)+mpert1*((idir3-1) & 2985 + 3*(ipert3-1))))) 2986 2987 ! Note that the loop order (1,2,3) is not really consistent 2988 ! with the d2E case (2, 1) 2989 ! TODO Clean this up 2990 2991 if ((ipert1 <= mpert2).and.(ipert2<=mpert2).and.(ipert3<=mpert2)) then 2992 if (d3flg(idir1,ipert1,idir2,ipert2,idir3,ipert3)>0) then 2993 ddb1%flg(ii,iblok1) = d3flg(idir1,ipert1,idir2,ipert2,idir3,ipert3) 2994 ddb1%val(:,ii,iblok1) = d3matr(:,idir1,ipert1,idir2,ipert2,idir3,ipert3) 2995 end if 2996 end if 2997 2998 end do 2999 end do 3000 end do 3001 end do 3002 end do 3003 end do 3004 ABI_SFREE(d3matr) 3005 ABI_SFREE(d3flg) 3006 3007 else if (is_type_d2eig(blktyp)) then 3008 ! ---------------- 3009 ! Skip d2eig block 3010 ! ---------------- 3011 3012 ! TODO need a function ddb_merge_d2eig(filename1, filename2, ) 3013 3014 end if ! blktyp 3015 3016 end subroutine ddb_merge_blocks
m_ddb/ddb_read_block_txt [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_read_block_txt
FUNCTION
Read the next block of data from a DDB in text format.
INPUTS
iblok=the blok index to be assigned mpert=maximum number of ipert msize=maximum size of the arrays flags and values nunit=unit number for the data block file
OUTPUT
(see side effects)
SIDE EFFECTS
Input/Output ddb = ddb block datastructure ddb%typ=type of the block: 0 => total energy 1 => second-order energy derivatives, non-stationary block 2 => second-order energy derivatives, stationary block 3 => third-order energy derivatives 4 => first-order energy derivatives: forces, stresses and polarization 5 => second-order eigenvalue derivatives ddb%flg(msize)=flag for every matrix element (0=> the element is not in the data block), (1=> the element is in the data blok) ddb%qpt(9)=wavevector of the perturbation(s). The elements from 1 to 3 are used if we are dealing with the 2nd derivative of total energy (only one wavevector), while all elements are used in case of a third order derivative of total energy (three wavevector could be present) ddb%nrm(3)=normalization factors for the three allowed wavevectors. ddb%val(2,msize)=real(dp), complex, value of the matrix elements that are present in the data block [blkval2(2,msize,mband,nkpt)]= value of the matrix elements that are present in a block of EIGR2D/EIGI2D
NOTES
only executed by one processor.
SOURCE
1659 subroutine ddb_read_block_txt(ddb,iblok,mband,mpert,msize,nkpt,nunit,& 1660 blkval2,kpt) !optional 1661 1662 !Arguments ------------------------------- 1663 !scalars 1664 integer,intent(in) :: mband,mpert,msize,nkpt,nunit 1665 integer, intent(in) :: iblok 1666 !logical, intent(in), optional :: eig2d 1667 class(ddb_type),intent(inout) :: ddb 1668 !arrays 1669 real(dp),intent(out),optional :: kpt(3,nkpt) 1670 real(dp),intent(out),optional :: blkval2(2,msize,mband,nkpt) 1671 1672 !Local variables ------------------------- 1673 !scalars 1674 integer :: band,iband,idir1,idir2,idir3,ii,ikpt,index,ipert1,ipert2,ipert3,nelmts 1675 logical :: eig2d_ 1676 real(dp) :: ai,ar 1677 character(len=32) :: name 1678 character(len=500) :: msg 1679 1680 ! ********************************************************************* 1681 1682 ! Zero every flag 1683 ddb%flg(1:msize, iblok)=0 1684 1685 eig2d_ = .false. 1686 1687 1688 if(present(kpt).and.present(blkval2)) then 1689 ! GA: Weird that it is not allocated here 1690 blkval2(:,:,:,:)=zero 1691 kpt(:,:)=zero 1692 eig2d_ = .true. 1693 end if 1694 1695 !if (present(eig2d)) then 1696 ! eig2d_ = eig2d 1697 !end if 1698 1699 ! Read the block type and number of elements 1700 read(nunit,*) 1701 read(nunit, '(a32,12x,i12)' )name,nelmts 1702 1703 ! TODO: Replace with STRING_d2E, etc. 1704 ! GA: Note that older versions used the expression '2rd' instead of '2nd' 1705 ! So this substitution needs to be checked for backward compatibility. 1706 ! Also, the strings for d2eig and d2eig_brd are undistinguishable 1707 ! I don't think the d2eig_brd was ever read by abinit or anaddb. 1708 if(name==' 2nd derivatives (non-stat.) - ' .or. name==' 2rd derivatives (non-stat.) - ')then 1709 ddb%typ(iblok)=BLKTYP_d2E_ns 1710 else if(name==' 2nd derivatives (stationary) - ' .or. name==' 2rd derivatives (stationary) - ')then 1711 ddb%typ(iblok)=BLKTYP_d2E_st 1712 else if(name==' 3rd derivatives - ')then 1713 ddb%typ(iblok)=BLKTYP_d3E_xx 1714 else if(name==' Total energy - ')then 1715 ddb%typ(iblok)=BLKTYP_d0E_xx 1716 else if(name==' 1st derivatives - ')then 1717 ddb%typ(iblok)=BLKTYP_d1E_xx 1718 else if(name==' 2nd eigenvalue derivatives - ' .or. name==' 2rd eigenvalue derivatives - ')then 1719 ddb%typ(iblok)=BLKTYP_d2eig_re 1720 else if(name==' 3rd derivatives (long wave) - ')then 1721 ddb%typ(iblok)=BLKTYP_d3E_lw 1722 else if(name==' 2nd derivatives (MBC) - ')then 1723 ddb%typ(iblok)=BLKTYP_d2E_mbc 1724 else 1725 write(msg,'(6a)')& 1726 'The following string appears in the DDB in place of',& 1727 ' the block type description :',ch10,trim(name),ch10,& 1728 'Action: check your DDB.' 1729 ABI_ERROR(msg) 1730 end if 1731 1732 ! Read the 2nd derivative block 1733 if (is_type_d2E(ddb%typ(iblok))) then 1734 1735 ! First check if there is enough space to read it 1736 if(msize<(3*mpert*3*mpert))then 1737 write(msg,'(3a)')& 1738 'There is not enough space to read a second-derivative block.',ch10,& 1739 'Action: increase msize and recompile.' 1740 ABI_ERROR(msg) 1741 end if 1742 1743 ! Read the phonon wavevector 1744 read(nunit, '(4x,3es16.8,f6.1)' )(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok) 1745 1746 ! Read every element 1747 do ii=1,nelmts 1748 read(nunit,*)idir1,ipert1,idir2,ipert2,ar,ai 1749 index=idir1+3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1))) 1750 ddb%flg(index,iblok)=1 1751 ddb%val(1,index,iblok)=ar 1752 ddb%val(2,index,iblok)=ai 1753 end do 1754 1755 else if (is_type_d3E(ddb%typ(iblok))) then 1756 ! Read the 3rd derivative block 1757 1758 ! First check if there is enough space to read it 1759 if(msize<(3*mpert*3*mpert*3*mpert))then 1760 write(msg, '(a,a,a,i10,a,i10,a,a,a)' )& 1761 'There is not enough space to read a third-derivative block.',ch10,& 1762 'The size provided is only ',msize,' although ',3*mpert*3*mpert*3*mpert,' is needed.',ch10,& 1763 'Action: increase msize and recompile.' 1764 ABI_ERROR(msg) 1765 end if 1766 1767 ! Read the perturbation wavevectors 1768 read(nunit,'(4x,3es16.8,f6.1)')(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok) 1769 read(nunit,'(4x,3es16.8,f6.1)')(ddb%qpt(ii,iblok),ii=4,6),ddb%nrm(2,iblok) 1770 read(nunit,'(4x,3es16.8,f6.1)')(ddb%qpt(ii,iblok),ii=7,9),ddb%nrm(3,iblok) 1771 1772 ! Read every element 1773 do ii=1,nelmts 1774 read(nunit,*)idir1,ipert1,idir2,ipert2,idir3,ipert3,ar,ai 1775 index=idir1+ & 1776 3*((ipert1-1)+mpert*((idir2-1)+ & 1777 3*((ipert2-1)+mpert*((idir3-1)+3*(ipert3-1))))) 1778 ddb%flg(index,iblok)=1 1779 ddb%val(1,index,iblok)=ar 1780 ddb%val(2,index,iblok)=ai 1781 end do 1782 1783 1784 else if (is_type_d0E(ddb%typ(iblok))) then 1785 ! Read the total energy 1786 ! First check if there is enough space to read it 1787 if(msize<1)then 1788 write(msg, '(3a,i0,3a)' )& 1789 'There is not enough space to read a total energy block.',ch10,& 1790 'The size provided is only ',msize,' although 1 is needed.',ch10,& 1791 'Action: increase msize and recompile.' 1792 ABI_ERROR(msg) 1793 end if 1794 1795 ! Read the total energy 1796 read(nunit,'(2d22.14)')ar,ai 1797 ddb%flg(1,iblok)=1 1798 ddb%val(1,1,iblok)=ar 1799 ddb%val(2,1,iblok)=ai 1800 1801 1802 else if (is_type_d1E(ddb%typ(iblok))) then 1803 ! Read the 1st derivative block 1804 ! First check if there is enough space to read it 1805 if (msize < (3*mpert)) then 1806 write(msg, '(3a,i0,a,i0,3a)' )& 1807 'There is not enough space to read a first-derivative block.',ch10,& 1808 'The size provided is only ',msize,' although ',3*mpert,' is needed.',ch10,& 1809 'Action: increase msize and recompile.' 1810 ABI_ERROR(msg) 1811 end if 1812 1813 ! Read every element 1814 do ii=1,nelmts 1815 read(nunit,*)idir1,ipert1,ar,ai 1816 index=idir1 + 3*(ipert1 - 1) 1817 ddb%flg(index,iblok)=1 1818 ddb%val(1,index,iblok)=ar 1819 ddb%val(2,index,iblok)=ai 1820 end do 1821 1822 1823 else if (is_type_d2eig(ddb%typ(iblok))) then 1824 1825 ! Read the 2nd eigenvalue derivative block 1826 ! First check if there is enough space to read it 1827 if(msize<(3*mpert*3*mpert))then 1828 write(msg, '(3a,i0,a,i0,3a)' )& 1829 'There is not enough space to read a second-derivative block.',ch10,& 1830 'The size provided is only ',msize,' although ',3*mpert*3*mpert*mband*nkpt,' is needed.',ch10,& 1831 'Action: increase msize and recompile.' 1832 ABI_ERROR(msg) 1833 end if 1834 1835 ! Read the phonon wavevector 1836 read(nunit, '(4x,3es16.8,f6.1)' )(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok) 1837 1838 ! Read the K point and band 1839 if (eig2d_) then 1840 do ikpt=1,nkpt 1841 read(nunit, '(9x,3es16.8)')(kpt(ii,ikpt),ii=1,3) 1842 do iband=1,mband 1843 read(nunit, '(6x,i3)') band 1844 ! Read every element 1845 do ii=1,nelmts 1846 read(nunit,*)idir1,ipert1,idir2,ipert2,ar,ai 1847 index=idir1+3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1))) 1848 ddb%flg(index,iblok)=1 1849 blkval2(1,index,iband,ikpt)=ar 1850 blkval2(2,index,iband,ikpt)=ai 1851 end do !nelmts 1852 end do !band 1853 end do !kpt 1854 end if 1855 end if 1856 1857 end subroutine ddb_read_block_txt
m_ddb/ddb_read_d0E_nc [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_read_d0E_nc
FUNCTION
Read a DDB block containing 0th order derivatives of energy.
INPUTS
ncid=netcdf identifier of a file open in reading mode. iblok=index of the block we are setting. iblok_d0E=index of the block we are reading in the d0E group.
OUTPUT
SOURCE
5289 subroutine ddb_read_d0E_nc(ddb, ncid, iblok, iblok_d0E) 5290 5291 !Arguments ------------------------------- 5292 !scalars 5293 class(ddb_type),intent(inout) :: ddb 5294 integer,intent(in) :: ncid,iblok,iblok_d0E 5295 5296 !Local variables ------------------------- 5297 !scalars 5298 integer :: ncid_d0E 5299 integer :: ncerr 5300 !arrays 5301 integer :: flg(1) 5302 real(dp) :: val(1) 5303 5304 ! ************************************************************************ 5305 5306 ncid_d0E = nctk_idgroup(ncid, 'd0E') 5307 5308 ! Allocate temporary arrays 5309 ncerr = nf90_get_var(ncid_d0E, nctk_idname(ncid_d0E, 'matrix_values'), val, start=[1,1,iblok_d0E], count=[1,1,1]) 5310 NCF_CHECK(ncerr) 5311 ddb%val(1,1,iblok) = val(1) 5312 ddb%val(2,1,iblok) = zero 5313 ncerr = nf90_get_var(ncid_d0E, nctk_idname(ncid_d0E, 'matrix_mask'), flg, start=[1,iblok_d0E], count=[1,1]) 5314 NCF_CHECK(ncerr) 5315 ddb%flg(1,iblok) = flg(1) 5316 5317 end subroutine ddb_read_d0E_nc
m_ddb/ddb_read_d1E_nc [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_read_d1E_nc
FUNCTION
Read a DDB block containing 1st order derivatives of energy.
INPUTS
ncid=netcdf identifier of a file open in reading mode. iblok=index of the block we are setting. iblok_d1E=index of the block we are reading in the d1E group.
OUTPUT
SOURCE
5339 subroutine ddb_read_d1E_nc(ddb, ncid, iblok, iblok_d1E) 5340 5341 !Arguments ------------------------------- 5342 !scalars 5343 class(ddb_type),intent(inout) :: ddb 5344 integer,intent(in) :: ncid,iblok,iblok_d1E 5345 5346 !Local variables ------------------------- 5347 !scalars 5348 integer :: ncid_d1E 5349 integer :: ncerr 5350 !arrays 5351 integer,allocatable :: flg_d1E(:,:) 5352 real(dp),allocatable :: matrix_d1E(:,:,:) 5353 5354 ! ************************************************************************ 5355 5356 ncid_d1E = nctk_idgroup(ncid, 'd1E') 5357 5358 ! Allocate temporary arrays 5359 ABI_MALLOC(matrix_d1E, (2,3,ddb%mpert)) 5360 ABI_MALLOC(flg_d1E, (3,ddb%mpert)) 5361 5362 ncerr = nf90_get_var(ncid_d1E, nctk_idname(ncid_d1E, 'matrix_values'), matrix_d1E, start=[1,1,1,iblok_d1E]) 5363 NCF_CHECK(ncerr) 5364 ncerr = nf90_get_var(ncid_d1E, nctk_idname(ncid_d1E, 'matrix_mask'), flg_d1E, start=[1,1,iblok_d1E]) 5365 NCF_CHECK(ncerr) 5366 5367 ! Reshape 5368 call ddb%set_d1matr(iblok, matrix_d1E, flg_d1E) 5369 5370 ! Free memory 5371 ABI_FREE(matrix_d1E) 5372 ABI_FREE(flg_d1E) 5373 5374 end subroutine ddb_read_d1E_nc
m_ddb/ddb_read_d2E_nc [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_read_d2E_nc
FUNCTION
Read a DDB block containing 2nd order derivatives of energy.
INPUTS
ncid=netcdf identifier of a file open in reading mode. iblok=index of the block we are setting. iblok_d2E=index of the block we are reading in the d2E group.
OUTPUT
SOURCE
5395 subroutine ddb_read_d2E_nc(ddb, ncid, iblok, iblok_d2E) 5396 5397 !Arguments ------------------------------- 5398 !scalars 5399 class(ddb_type),intent(inout) :: ddb 5400 integer,intent(in) :: ncid,iblok,iblok_d2E 5401 5402 !Local variables ------------------------- 5403 !scalars 5404 integer :: ncid_d2E 5405 integer :: ncerr 5406 !arrays 5407 real(dp) :: qpt(3) 5408 integer,allocatable :: flg_d2E(:,:,:,:) 5409 real(dp),allocatable :: matrix_d2E(:,:,:,:,:) 5410 5411 ! ************************************************************************ 5412 5413 ncid_d2E = nctk_idgroup(ncid, 'd2E') 5414 5415 ! Allocate temporary arrays 5416 ABI_MALLOC(matrix_d2E, (2,3,ddb%mpert,3,ddb%mpert)) 5417 ABI_MALLOC(flg_d2E, (3,ddb%mpert,3,ddb%mpert)) 5418 5419 ncerr = nf90_get_var(ncid_d2E, nctk_idname(ncid_d2E, 'reduced_coordinates_of_qpoints'), qpt, start=[1,iblok_d2E]) 5420 NCF_CHECK(ncerr) 5421 ddb%qpt(1:3,iblok) = qpt(:) 5422 ncerr = nf90_get_var(ncid_d2E, nctk_idname(ncid_d2E, 'qpoints_normalization'), ddb%nrm(1,iblok), start=[iblok_d2E]) 5423 NCF_CHECK(ncerr) 5424 5425 ncerr = nf90_get_var(ncid_d2E, nctk_idname(ncid_d2E, 'matrix_values'), matrix_d2E, start=[1,1,1,1,1,iblok_d2E]) 5426 NCF_CHECK(ncerr) 5427 ncerr = nf90_get_var(ncid_d2E, nctk_idname(ncid_d2E, 'matrix_mask'), flg_d2E, start=[1,1,1,1,iblok_d2E]) 5428 NCF_CHECK(ncerr) 5429 5430 ! Reshape 5431 call ddb%set_d2matr(iblok, matrix_d2E, flg_d2E) 5432 5433 ! Free memory 5434 ABI_FREE(matrix_d2E) 5435 ABI_FREE(flg_d2E) 5436 5437 end subroutine ddb_read_d2E_nc
m_ddb/ddb_read_d2eig [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_read_d2eig
FUNCTION
Read the next DDB block containing second-order derivatives of eigenvalues and store it in block number iblok. The values of nband and nkpt must be set.
INPUTS
ddb_hdr=ddb header object with open file. iblok_store=the block index in the ddb object iblok_read=the block index in the ddb file
OUTPUT
NOTE The ddb object must be allocated becore calling this routine.
SOURCE
1885 subroutine ddb_read_d2eig(ddb, ddb_hdr, iblok_store, iblok_read, comm) 1886 1887 !Arguments ------------------------------- 1888 !scalars 1889 class(ddb_type),intent(inout) :: ddb 1890 type(ddb_hdr_type),intent(in) :: ddb_hdr 1891 integer, intent(in) :: iblok_store 1892 integer, intent(in),optional :: iblok_read 1893 integer, intent(in),optional :: comm 1894 1895 !Local variables ------------------------- 1896 !scalars 1897 integer,parameter :: master=0 1898 integer :: comm_ 1899 character(len=500) :: msg 1900 1901 ! ********************************************************************* 1902 1903 if (present(comm)) then 1904 comm_ = comm 1905 else 1906 comm_ = xmpi_comm_self 1907 end if 1908 1909 if (xmpi_comm_rank(comm_) == master) then 1910 1911 if (ddb_hdr%has_open_file_nc) then 1912 1913 ! Read the specified block and store it 1914 call ddb%read_d2eig_nc(ddb_hdr%ncid, iblok_store, iblok_read) 1915 1916 else if (ddb_hdr%has_open_file_txt) then 1917 1918 ! Read the next block and store it 1919 call ddb%read_d2eig_txt(ddb_hdr%unddb, iblok_store) 1920 1921 else 1922 write(msg, '(3a)' )& 1923 ! File has not beed open by ddb_hdr 1924 'Attempting to read from unopen file DDB.',ch10,& 1925 'Action: contact Abinit group.' 1926 ABI_ERROR(msg) 1927 end if 1928 1929 end if 1930 1931 ! GA: Should in principle broadcast the d2eig array, 1932 ! but I dont think it is required yet. 1933 1934 end subroutine ddb_read_d2eig
m_ddb/ddb_read_d2eig_nc [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_read_d2eig_nc
FUNCTION
Read a DDB block containing 2nd order derivatives of eigenvalues.
INPUTS
ncid=netcdf identifier of a file open in reading mode. iblok=index of the block we are setting. iblok_d2eig=index of the block we are reading in the d2eig group.
OUTPUT
SOURCE
5534 subroutine ddb_read_d2eig_nc(ddb, ncid, iblok, iblok_d2eig) 5535 5536 !Arguments ------------------------------- 5537 !scalars 5538 class(ddb_type),intent(inout) :: ddb 5539 integer,intent(in) :: ncid,iblok 5540 integer,intent(in),optional :: iblok_d2eig 5541 5542 !Local variables ------------------------- 5543 !scalars 5544 integer :: ncid_d2eig,ncerr 5545 integer :: nkpt_file 5546 integer :: nblok_d2eig 5547 integer :: iblok_, iblok_d2eig_ 5548 integer :: iband, jband, bandshift, isppol, mband 5549 integer :: ikpt,ipert1,idir1,ipert2,idir2,ii 5550 character(len=500) :: msg 5551 !arrays 5552 integer,allocatable :: flg_d2eig(:,:,:,:) 5553 real(dp) :: qpt(3) 5554 real(dp),allocatable :: nrm(:) 5555 real(dp),allocatable :: matrix_d2eig(:,:,:,:,:,:,:) 5556 real(dp),allocatable :: matrix_d2eig_isppol(:,:,:,:,:,:,:) 5557 5558 ! ************************************************************************ 5559 5560 ncid_d2eig = nctk_idgroup(ncid, 'd2eig') 5561 5562 if (present(iblok_d2eig)) then 5563 iblok_d2eig_= iblok_d2eig 5564 else 5565 ! Recount the blok index 5566 iblok_d2eig_ = 0 5567 do iblok_=1,iblok 5568 if (is_type_d2eig(ddb%typ(iblok_))) then 5569 iblok_d2eig_ = iblok_d2eig_ + 1 5570 end if 5571 end do 5572 end if 5573 5574 ! Sanity check on dimensions 5575 if (MOD(ddb%nband, ddb%nsppol)/=0) then 5576 write(msg,'(a,i5,a,i5)') 'ddb was allocated with nband=',ddb%nband,& 5577 ' but nsppol=',ddb%nsppol 5578 ABI_ERROR(msg) 5579 end if 5580 5581 ! Read kpoints 5582 NCF_CHECK(nctk_get_dim(ncid, "number_of_kpoints", nkpt_file)) 5583 ncerr = nf90_get_var(ncid, nctk_idname(ncid, 'reduced_coordinates_of_kpoints'), ddb%kpt, count=[3,nkpt_file]) 5584 NCF_CHECK(ncerr) 5585 5586 mband = ddb%nband / ddb%nsppol 5587 5588 ncerr = nf90_get_var(ncid_d2eig, nctk_idname(ncid_d2eig,& 5589 'reduced_coordinates_of_qpoints'),& 5590 qpt,& 5591 start=[1,iblok_d2eig_]) 5592 NCF_CHECK(ncerr) 5593 5594 ddb%qpt(:,iblok) = zero 5595 ddb%qpt(1:3,iblok) = qpt 5596 5597 !ncerr = nf90_get_var(ncid_d2eig, nctk_idname(ncid_d2eig,& 5598 ! 'qpoints_normalization'),& 5599 ! nrm(1,iblok),& 5600 ! start=[iblok_d2eig_]) 5601 NCF_CHECK(nctk_get_dim(ncid_d2eig, "number_of_d2eig_blocks", nblok_d2eig)) 5602 ABI_MALLOC(nrm, (nblok_d2eig)) 5603 ncerr = nf90_get_var(ncid_d2eig, nctk_idname(ncid_d2eig,& 5604 'qpoints_normalization'),& 5605 nrm) 5606 NCF_CHECK(ncerr) 5607 ddb%nrm(:,iblok) = zero 5608 ddb%nrm(1,iblok) = nrm(iblok_d2eig_) 5609 ABI_FREE(nrm) 5610 5611 5612 ABI_MALLOC(matrix_d2eig, (2,3,ddb%mpert,3,ddb%mpert,ddb%nband,ddb%nkpt)) 5613 ABI_MALLOC(matrix_d2eig_isppol, (2,3,ddb%mpert,3,ddb%mpert,mband,ddb%nkpt)) 5614 ABI_MALLOC(flg_d2eig, (3,ddb%mpert,3,ddb%mpert)) 5615 5616 do isppol=1,ddb%nsppol 5617 5618 ncerr = nf90_get_var(ncid_d2eig, nctk_idname(ncid_d2eig,& 5619 'matrix_values'),& 5620 matrix_d2eig_isppol,& 5621 start=[1,1,1,1,1,1,1,isppol,iblok_d2eig_]) 5622 NCF_CHECK(ncerr) 5623 5624 if (ddb%nsppol==1) then 5625 matrix_d2eig(:,:,:,:,:,:,:) = matrix_d2eig_isppol(:,:,:,:,:,:,:) 5626 else 5627 bandshift = (isppol - 1) * mband 5628 do ikpt=1,ddb%nkpt 5629 do iband=1,ddb%nband 5630 jband = bandshift + iband 5631 do ipert1=1,ddb%mpert 5632 do idir1=1,3 5633 do ipert2=1,ddb%mpert 5634 do idir2=1,3 5635 do ii=1,2 5636 matrix_d2eig(ii,idir2,ipert2,idir1,ipert1,jband,ikpt)=& 5637 matrix_d2eig_isppol(ii,idir2,ipert2,idir1,ipert1,iband,ikpt) 5638 end do 5639 end do 5640 end do 5641 end do 5642 end do 5643 end do 5644 end do 5645 end if 5646 end do 5647 5648 ncerr = nf90_get_var(ncid_d2eig, nctk_idname(ncid_d2eig,& 5649 'matrix_mask'),& 5650 flg_d2eig,& 5651 start=[1,1,1,1,iblok_d2eig_]) 5652 NCF_CHECK(ncerr) 5653 5654 ! Store values 5655 call ddb%set_d2eig(iblok, matrix_d2eig, flg_d2eig) 5656 5657 ! Free memory 5658 ABI_FREE(matrix_d2eig) 5659 ABI_FREE(matrix_d2eig_isppol) 5660 ABI_FREE(flg_d2eig) 5661 5662 end subroutine ddb_read_d2eig_nc
m_ddb/ddb_read_d2eig_txt [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_read_d2eig_txt
FUNCTION
Read the next DDB block containing second-order derivatives of eigenvalues and store it in block number iblok. The ddb object must have been allocated with nband and nkpt.
INPUTS
unddb=unit for the open file in text format iblok=the block index in the ddb object
OUTPUT
SOURCE
1958 subroutine ddb_read_d2eig_txt(ddb, unddb, iblok) 1959 1960 !Arguments ------------------------------- 1961 !scalars 1962 class(ddb_type),intent(inout) :: ddb 1963 integer, intent(in) :: unddb 1964 integer, intent(in), optional :: iblok 1965 !Local variables ------------------------- 1966 !scalars 1967 integer :: iblok_eig2d 1968 1969 ! ********************************************************************* 1970 1971 iblok_eig2d = 1 1972 if (present(iblok)) iblok_eig2d = iblok 1973 1974 ! GA: Here, nband should really be nband * nsppol. 1975 ! but this is the responsibility of the calling routine 1976 ! see thmeig and merge_ddb 1977 ! FIXME This is inconsistent with ddb_malloc_d2eig... 1978 ! I think I should change this with ddb%nband * ddb%nsppol 1979 call ddb%read_block_txt(iblok_eig2d,ddb%nband,ddb%mpert,ddb%msize,ddb%nkpt,unddb,& 1980 ddb%eig2dval(:,:,:,:),ddb%kpt(:,:)) 1981 1982 end subroutine ddb_read_d2eig_txt
m_ddb/ddb_read_d3E_nc [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_read_d3E_nc
FUNCTION
Read a DDB block containing 3rd order derivatives of energy.
INPUTS
ncid=netcdf identifier of a file open in reading mode. iblok=index of the block we are setting. iblok_d3E=index of the block we are reading in the d3E group.
OUTPUT
SOURCE
5458 subroutine ddb_read_d3E_nc(ddb, ncid, iblok, iblok_d3E) 5459 5460 !Arguments ------------------------------- 5461 !scalars 5462 class(ddb_type),intent(inout) :: ddb 5463 integer,intent(in) :: ncid,iblok,iblok_d3E 5464 5465 !Local variables ------------------------- 5466 !scalars 5467 integer :: blktyp 5468 integer :: ncid_d3E 5469 integer :: ncerr 5470 !arrays 5471 real(dp) :: qpt(3), nrm(3) 5472 real(dp),allocatable :: matrix_d3E(:,:,:,:,:,:,:) 5473 integer,allocatable :: flg_d3E(:,:,:,:,:,:) 5474 5475 ! ************************************************************************ 5476 5477 ncid_d3E = nctk_idgroup(ncid, 'd3E') 5478 5479 ! Allocate temporary arrays 5480 ABI_MALLOC(matrix_d3E, (2,3,ddb%mpert,3,ddb%mpert,3,ddb%mpert)) 5481 ABI_MALLOC(flg_d3E, (3,ddb%mpert,3,ddb%mpert,3,ddb%mpert)) 5482 5483 ncerr = nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'reduced_coordinates_of_qpoints'),qpt,start=[1,1,iblok_d3E],count=[1,3,1]) 5484 NCF_CHECK(ncerr) 5485 ddb%qpt(1:3,iblok) = qpt(:) 5486 5487 ncerr = nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'reduced_coordinates_of_qpoints'),qpt,start=[2,1,iblok_d3E],count=[1,3,1]) 5488 NCF_CHECK(ncerr) 5489 ddb%qpt(4:6,iblok) = qpt(:) 5490 5491 ncerr = nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'reduced_coordinates_of_qpoints'),qpt,start=[3,1,iblok_d3E],count=[1,3,1]) 5492 NCF_CHECK(ncerr) 5493 ddb%qpt(7:9,iblok) = qpt(:) 5494 5495 ncerr = nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'qpoints_normalization'), nrm, start=[1,iblok_d3E],count=[3,1]) 5496 NCF_CHECK(ncerr) 5497 ddb%nrm(:,iblok) = nrm(:) 5498 5499 NCF_CHECK(nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'matrix_values'), matrix_d3E, start=[1,1,1,1,1,1,1,iblok_d3E])) 5500 NCF_CHECK(nf90_get_var(ncid_d3E, nctk_idname(ncid_d3E, 'matrix_mask'), flg_d3E, start=[1,1,1,1,1,1,iblok_d3E])) 5501 5502 5503 blktyp = ddb%typ(iblok) ! Save block type so it doesnt get overwritten. 5504 5505 call ddb%set_d3matr(iblok, matrix_d3E, flg_d3E) 5506 5507 ddb%typ(iblok) = blktyp 5508 5509 ! Free memory 5510 ABI_FREE(matrix_d3E) 5511 ABI_FREE(flg_d3E) 5512 5513 end subroutine ddb_read_d3E_nc
m_ddb/ddb_read_nc [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_read_nc
FUNCTION
This subroutine reads data from the DDB.nc file and constructs an instance of ddb_type It also returns an instance of crystal_t with the crystalline structure reported in the DDB file and the DDB header.
INPUTS
filename=DDB filename. comm=MPI communicator. prtvol=Verbosity level raw = 1 -> do not perform any symetrization or transformation to cartesian coordinates. 0 (default) -> do perform these transformations.
OUTPUT
ddb<type(ddb_type)>=Object storing the DDB results. crystal<type(crystal_t)>=Crystal structure parameters ddb_hdr= Header of the DDB file.
SOURCE
2659 subroutine ddb_read_nc(ddb, filename, ddb_hdr, crystal, comm, prtvol, raw) 2660 2661 !Arguments ------------------------------- 2662 !scalars 2663 class(ddb_type),intent(inout) :: ddb 2664 integer,intent(in) :: comm 2665 integer,optional,intent(in) :: prtvol, raw 2666 character(len=*),intent(in) :: filename 2667 type(crystal_t),intent(out) :: crystal 2668 type(ddb_hdr_type),intent(out) :: ddb_hdr 2669 !array 2670 2671 !Local variables------------------------------- 2672 !scalars 2673 integer,parameter :: master=0 2674 integer :: prtvol_, raw_ 2675 integer :: ncid 2676 integer :: iblok,iblok_d0E,iblok_d1E,iblok_d2E,iblok_d3E,iblok_d2eig 2677 2678 !arrays 2679 !character(len=132),allocatable :: title(:) 2680 2681 ! ************************************************************************ 2682 2683 DBG_ENTER("COLL") 2684 2685 if (present(raw)) then 2686 raw_ = raw 2687 else 2688 raw_ = 0 2689 end if 2690 2691 ! GA: Not really used so far 2692 if (present(prtvol)) then 2693 prtvol_ = prtvol 2694 else 2695 prtvol_ = 0 2696 end if 2697 2698 ! Read header 2699 call ddb_hdr%open_read_nc(filename, comm) 2700 ncid = ddb_hdr%ncid 2701 2702 if (xmpi_comm_rank(comm) == master) then 2703 2704 ddb%nsppol = ddb_hdr%nsppol 2705 2706 ! Copy dimensions from header and allocate arrays 2707 call ddb%malloc(ddb_hdr%msize, ddb_hdr%nblok, ddb_hdr%natom, & 2708 ddb_hdr%ntypat, ddb_hdr%mpert,& 2709 ddb_hdr%nkpt, ddb_hdr%mband) 2710 2711 ! Copy arrays from header 2712 ddb%typ(:) = ddb_hdr%typ(:) 2713 ddb%amu(:) = ddb_hdr%crystal%amu(:) 2714 ddb%acell(:) = one 2715 ddb%rprim(:,:) = ddb_hdr%crystal%rprimd(:,:) 2716 ddb%gprim(:,:) = ddb_hdr%crystal%gprimd(:,:) 2717 2718 ! --------------- 2719 ! Read all blocks 2720 ! --------------- 2721 iblok_d0E = 0 2722 iblok_d1E = 0 2723 iblok_d2E = 0 2724 iblok_d3E = 0 2725 iblok_d2eig = 0 2726 2727 do iblok=1,ddb%nblok 2728 2729 if (is_type_d0E(ddb%typ(iblok))) then 2730 iblok_d0E = iblok_d0E + 1 2731 call ddb%read_d0E_nc(ncid, iblok, iblok_d0E) 2732 2733 else if (is_type_d1E(ddb%typ(iblok))) then 2734 iblok_d1E = iblok_d1E + 1 2735 call ddb%read_d1E_nc(ncid, iblok, iblok_d1E) 2736 2737 else if (is_type_d2E(ddb%typ(iblok))) then 2738 iblok_d2E = iblok_d2E + 1 2739 call ddb%read_d2E_nc(ncid, iblok, iblok_d2E) 2740 2741 else if (is_type_d3E(ddb%typ(iblok))) then 2742 iblok_d3E = iblok_d3E + 1 2743 call ddb%read_d3E_nc(ncid, iblok, iblok_d3E) 2744 2745 else if (is_type_d2eig(ddb%typ(iblok))) then 2746 iblok_d2eig = iblok_d2eig + 1 2747 ! GA: It is kind of weird to call this function inside a loop, 2748 ! because the ddb can only hold a single block of d2eig data. 2749 call ddb%read_d2eig_nc(ncid, iblok, iblok_d2eig) 2750 2751 end if 2752 2753 ! Symmetrize and transform if raw==0 2754 if (raw_==0) then 2755 call ddb%symmetrize_and_transform(ddb_hdr%crystal,iblok) 2756 end if 2757 2758 end do 2759 2760 end if 2761 2762 ! Close the file 2763 call ddb_hdr%close() 2764 2765 ! -------------- 2766 ! Broadcast data 2767 ! -------------- 2768 if (xmpi_comm_size(comm) > 1) then 2769 call ddb%bcast(comm) 2770 call ddb_hdr%bcast(comm) 2771 end if 2772 2773 ! Copy crystal 2774 call ddb_hdr%crystal%copy(crystal) 2775 2776 DBG_EXIT("COLL") 2777 2778 end subroutine ddb_read_nc
m_ddb/ddb_read_txt [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_read_txt
FUNCTION
This subroutine reads data from the DDB file and constructs an instance of ddb_type It also returns an instance of crystal_t with the crystalline structure reported in the DDB file and the DDB header.
INPUTS
filename=DDB filename. comm=MPI communicator. prtvol=Verbosity level raw = 1 -> do not perform any symetrization or transformation to cartesian coordinates. 0 (default) -> do perform these transformations.
OUTPUT
ddb<type(ddb_type)>=Object storing the DDB results. crystal<type(crystal_t)>=Crystal structure parameters ddb_hdr= Header of the DDB file.
SOURCE
2473 subroutine ddb_read_txt(ddb, filename, ddb_hdr, crystal, comm, prtvol, raw) 2474 2475 !Arguments ------------------------------- 2476 !scalars 2477 class(ddb_type),intent(inout) :: ddb 2478 integer,intent(in) :: comm 2479 integer,optional,intent(in) :: prtvol, raw 2480 character(len=*),intent(in) :: filename 2481 type(crystal_t),intent(out) :: Crystal 2482 type(ddb_hdr_type),intent(out) :: ddb_hdr 2483 2484 !Local variables------------------------------- 2485 !scalars 2486 integer,parameter :: master=0 2487 integer :: msym,dimekb,lmnmax,mband,nkpt,ntypat,nsym,usepaw 2488 integer :: mpert,msize,natom,nblok,occopt,nsppol 2489 real(dp) :: ucvol 2490 2491 !arrays 2492 integer,allocatable :: symrec(:,:,:),symrel(:,:,:),symafm(:),indsym(:,:,:),typat(:) 2493 real(dp) :: acell(3),gmet(3,3),gprim(3,3),rmet(3,3),rprim(3,3) 2494 real(dp),allocatable :: amu(:),xcart(:),xred(:,:),zion(:),znucl(:),tnons(:,:) 2495 2496 ! ************************************************************************ 2497 2498 DBG_ENTER("COLL") 2499 2500 ! Must read natom from the DDB before being able to allocate some arrays needed for invars9 2501 call ddb_hdr%open_read_txt(filename, comm) 2502 2503 ! GA: clean this up. Not all of it is useful 2504 nblok = ddb_hdr%nblok 2505 msym = ddb_hdr%msym 2506 natom = ddb_hdr%natom 2507 ntypat = ddb_hdr%ntypat 2508 mband = ddb_hdr%mband 2509 nkpt = ddb_hdr%nkpt 2510 nsppol = ddb_hdr%nsppol 2511 usepaw = ddb_hdr%usepaw 2512 dimekb = ddb_hdr%psps%dimekb 2513 lmnmax = ddb_hdr%psps%lmnmax 2514 occopt = ddb_hdr%occopt 2515 mpert = ddb_hdr%mpert 2516 msize = ddb_hdr%msize 2517 2518 ! Master reads and then broadcasts data. 2519 if (xmpi_comm_rank(comm) == master) then 2520 2521 ! Allocate arrays depending on msym (which is actually fixed to nsym inside inprep8) 2522 ABI_MALLOC(symrel,(3,3,msym)) 2523 ABI_MALLOC(symafm,(msym)) 2524 ABI_MALLOC(tnons,(3,msym)) 2525 ABI_MALLOC(typat,(natom)) 2526 ABI_MALLOC(xred,(3,natom)) 2527 ABI_MALLOC(zion,(ntypat)) 2528 ABI_MALLOC(znucl,(ntypat)) 2529 2530 ABI_MALLOC(symrec,(3,3,msym)) 2531 ABI_MALLOC(indsym,(4,msym,natom)) 2532 ABI_MALLOC(xcart,(3*natom)) 2533 ABI_MALLOC(amu,(ntypat)) 2534 2535 ddb%nsppol = nsppol 2536 call ddb%malloc(msize, nblok, natom, ntypat, mpert) 2537 2538 ! GA: FIXME 2539 ! Should clean this up. Lots of the arguments are not needed. 2540 ! In particular, rprim and acell could be taken from ddb_hdr%crystal 2541 ! which is already initialized at this point 2542 call rdddb9(ddb, ddb_hdr, ddb_hdr%unddb,& 2543 acell,amu,gmet,gprim,indsym,& 2544 mband,mpert,msize,msym,& 2545 natom,nkpt,nsym,ntypat,& 2546 rmet,rprim,symrec,symrel,symafm,& 2547 tnons,typat,ucvol,xcart,xred,zion,znucl,raw) 2548 2549 ABI_FREE(symrec) 2550 ABI_FREE(indsym) 2551 ABI_FREE(xcart) 2552 2553 ! Save variables needed to call legacy code. 2554 ddb%acell = acell 2555 ddb%rprim = rprim 2556 ddb%gprim = gprim 2557 2558 !call ddb%set_brav(brav) 2559 2560 ! Other useful quantities. 2561 ! 2 is to preserve the old behaviour 2562 ddb%prtvol = 2; if (present(prtvol)) ddb%prtvol = prtvol 2563 ddb%occopt = occopt 2564 ddb%amu = amu 2565 ABI_FREE(amu) 2566 2567 ! These were not needed because crystal is already initialized in the header. 2568 ABI_FREE(symrel) 2569 ABI_FREE(symafm) 2570 ABI_FREE(tnons) 2571 ABI_FREE(typat) 2572 ABI_FREE(xred) 2573 ABI_FREE(zion) 2574 ABI_FREE(znucl) 2575 2576 end if 2577 2578 call ddb_hdr%close() 2579 2580 if (xmpi_comm_size(comm) > 1) then 2581 call ddb%bcast(comm) 2582 call ddb_hdr%bcast(comm) 2583 2584 !! GA: This seems superfluous now... 2585 !call xmpi_bcast(nsym, master, comm, ierr) 2586 !call xmpi_bcast(symrel, master, comm, ierr) 2587 !call xmpi_bcast(symafm, master, comm, ierr) 2588 !call xmpi_bcast(typat, master, comm, ierr) 2589 !call xmpi_bcast(acell, master, comm, ierr) 2590 !call xmpi_bcast(occopt, master, comm, ierr) 2591 !call xmpi_bcast(gprim, master, comm, ierr) 2592 !call xmpi_bcast(rprim, master, comm, ierr) 2593 !call xmpi_bcast(tnons, master, comm, ierr) 2594 !call xmpi_bcast(xred, master, comm, ierr) 2595 !call xmpi_bcast(zion, master, comm, ierr) 2596 !call xmpi_bcast(znucl, master, comm, ierr) 2597 end if 2598 2599 call ddb_hdr%crystal%copy(Crystal) 2600 2601 !! Initialize crystal_t object. 2602 !call mkrdim(acell,rprim,rprimd) 2603 2604 !! GA: These variables are hardcoded which means the crystal object 2605 !! is not reliable for antiferro systems or alchemical potentials 2606 !! when it is read from a text DDB file. 2607 !npsp = ntypat; space_group = 0; timrev = 2 2608 !use_antiferro=.FALSE. !; use_antiferro=(nspden==2.and.nsppol==1) 2609 !ABI_MALLOC(title, (ntypat)) 2610 2611 !do ii=1,ntypat 2612 ! write(title(ii),'(a,i0)')"No title for typat ",ii 2613 !end do 2614 2615 !! Warning znucl is dimensioned with ntypat = nspsp hence alchemy is not supported here 2616 !call crystal_init(ddb%amu,Crystal,space_group,natom,npsp,ntypat,nsym,rprimd,typat,xred,& 2617 ! zion,znucl,timrev,use_antiferro,.FALSE.,title,& 2618 ! symrel=symrel(:,:,1:nsym),tnons=tnons(:,1:nsym),symafm=symafm(1:nsym)) 2619 2620 !ABI_FREE(title) 2621 !ABI_FREE(symrel) 2622 !ABI_FREE(symafm) 2623 !ABI_FREE(tnons) 2624 !ABI_FREE(typat) 2625 !ABI_FREE(xred) 2626 !ABI_FREE(zion) 2627 !ABI_FREE(znucl) 2628 2629 DBG_EXIT("COLL") 2630 2631 end subroutine ddb_read_txt
m_ddb/ddb_set_brav [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_brav
FUNCTION
Modify the current values of rprim according to bravais lattice. Perform some checks on the primitive vectors before rescaling them such that rprim(1,2)=0.5
INPUTS
brav 1 -> No rescaling. other -> Check and rescale. Note that the meaning of brav is 1 or -1 -> simple lattice 2 -> face-centered cubic 3 -> body-centered lattice 4 -> hexagonal lattice (D6h)
OUTPUT
SOURCE
1166 subroutine ddb_set_brav(ddb, brav) 1167 1168 !Arguments ------------------------------- 1169 !array 1170 class(ddb_type),intent(inout) :: ddb 1171 !scalars 1172 integer,intent(in) :: brav 1173 1174 !Local variables------------------------------- 1175 !scalars 1176 real(dp) :: factor 1177 character(len=500) :: msg 1178 1179 ! ************************************************************************* 1180 1181 ! Renormalize rprim to possibly satisfy the constraint abs(rprim(1,2))=half when abs(brav)/=1 1182 ! This section is needed to preserver the behaviour of the old implementation. 1183 if (abs(brav)/=1 .and. abs(abs(ddb%rprim(1,2))-half)>tol10) then 1184 if(abs(ddb%rprim(1,2))<tol6)then 1185 write(msg, '(a,i0,7a)' )& 1186 'The input DDB value of brav is ',brav,',',ch10,& 1187 'and the one of rprim(1,2) is zero.',ch10,& 1188 'These are incompatible',ch10,& 1189 'Action: check the value of brav and rprim(1,2) in your DDB.' 1190 ABI_ERROR(msg) 1191 end if 1192 factor = abs(ddb%rprim(1,2)) * two 1193 ddb%acell(:) = ddb%acell(:) * factor 1194 ddb%rprim(:,:) = ddb%rprim(:,:) / factor 1195 ddb%gprim(:,:) = ddb%gprim(:,:) * factor 1196 end if 1197 1198 end subroutine ddb_set_brav
m_ddb/ddb_set_d1matr [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_d1matr
FUNCTION
Set values for the first-order derivative matrix.
INPUTS
iblok=index of the block being set. d1matr=the first-order derivative matrix. flg=flag to indicate presence of a given element.
SOURCE
1075 subroutine ddb_set_d1matr(ddb, iblok, d1matr, flg) 1076 1077 !Arguments ------------------------------- 1078 !array 1079 class(ddb_type),intent(inout) :: ddb 1080 real(dp), intent(in) :: d1matr(2,3,ddb%mpert) 1081 integer, intent(in) :: flg(3,ddb%mpert) 1082 !scalars 1083 integer,intent(in) :: iblok 1084 1085 !Local variables ------------------------- 1086 !scalars 1087 integer :: ii,ipert1,idir1 1088 1089 ! ************************************************************************ 1090 1091 ii=0 1092 do ipert1=1,ddb%mpert 1093 do idir1=1,3 1094 ii=ii+1 1095 ddb%val(1,ii,iblok) = d1matr(1,idir1,ipert1) 1096 ddb%val(2,ii,iblok) = d1matr(2,idir1,ipert1) 1097 ddb%flg(ii,iblok) = flg(idir1,ipert1) 1098 end do 1099 end do 1100 1101 end subroutine ddb_set_d1matr
m_ddb/ddb_set_d2eig [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_d2eig
FUNCTION
Set values for the second-order derivatives of eigenvalues.
INPUTS
iblok=index of the block we are setting. d2eig=the second-order derivative of eigenvalues. flg=flag to indicate presence of a given element.
OUTPUT
NOTE Does not handle spin index. Also, sometimes, d2eig is available with flat index
SOURCE
5884 subroutine ddb_set_d2eig(ddb, iblok, d2eig, flg) 5885 5886 !Arguments ------------------------------- 5887 !array 5888 class(ddb_type),intent(inout) :: ddb 5889 real(dp),intent(in) :: d2eig(2,3,ddb%mpert,3,ddb%mpert,ddb%nband,ddb%nkpt) 5890 integer,intent(in) :: flg(3,ddb%mpert,3,ddb%mpert) 5891 !scalars 5892 integer,intent(in) :: iblok 5893 5894 !Local variables ------------------------- 5895 !scalars 5896 integer :: idir1,idir2,ipert1,ipert2,index,iband,ikpt,ii 5897 5898 ! ************************************************************************ 5899 5900 do ikpt=1,ddb%nkpt 5901 do iband=1,ddb%nband 5902 ii = 0 5903 do ipert2=1,ddb%mpert 5904 do idir2=1,3 5905 do ipert1=1,ddb%mpert 5906 do idir1=1,3 5907 index=idir1+3*((ipert1-1)+ddb%mpert*((idir2-1)+3*(ipert2-1))) 5908 ddb%eig2dval(1,index,iband,ikpt)=d2eig(1,idir1,ipert1,idir2,ipert2,iband,ikpt) 5909 ddb%eig2dval(2,index,iband,ikpt)=d2eig(2,idir1,ipert1,idir2,ipert2,iband,ikpt) 5910 ddb%flg(index,iblok)=flg(idir1,ipert1,idir2,ipert2) 5911 end do !idir1 5912 end do !pert1 5913 end do !idir2 5914 end do !pert2 5915 end do !band 5916 end do !kpt 5917 5918 end subroutine ddb_set_d2eig
m_ddb/ddb_set_d2eig_reshape [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_d2eig_reshape
FUNCTION
Set values for the second-order derivatives of eigenvalues and reshape the array received.
INPUTS
iblok=index of the block we are setting. d2eig=the second-order derivative of eigenvalues. flg=flag to indicate presence of a given element. blktyp=block type 5->real part 6->imaginary part (broadening)
OUTPUT
SOURCE
5943 subroutine ddb_set_d2eig_reshape(ddb, iblok, d2eig, flg, blktyp) 5944 5945 !Arguments ------------------------------- 5946 !array 5947 class(ddb_type),intent(inout) :: ddb 5948 real(dp),intent(in) :: d2eig(2,ddb%nband*ddb%nsppol,ddb%nkpt,3,ddb%mpert,3,ddb%mpert) 5949 integer,intent(in) :: flg(3,ddb%mpert,3,ddb%mpert) 5950 !scalars 5951 integer,intent(in) :: iblok 5952 integer,intent(in),optional :: blktyp 5953 5954 !Local variables ------------------------- 5955 !scalars 5956 integer :: idir1,idir2,ipert1,ipert2,index,iband,ikpt,ii,mband 5957 5958 ! ************************************************************************ 5959 5960 ddb%typ(iblok) = BLKTYP_d2eig_re 5961 if (present(blktyp)) ddb%typ(iblok) = blktyp 5962 5963 ! Spin polarization is wrapped in band number 5964 mband = ddb%nband * ddb%nsppol 5965 5966 do ikpt=1,ddb%nkpt 5967 do iband=1,mband 5968 ii = 0 5969 do ipert2=1,ddb%mpert 5970 do idir2=1,3 5971 do ipert1=1,ddb%mpert 5972 do idir1=1,3 5973 index=idir1+3*((ipert1-1)+ddb%mpert*((idir2-1)+3*(ipert2-1))) 5974 ddb%flg(index,iblok)=flg(idir1,ipert1,idir2,ipert2) 5975 if (ddb%flg(index,iblok) > 0) then 5976 ddb%eig2dval(1,index,iband,ikpt)=d2eig(1,iband,ikpt,idir1,ipert1,idir2,ipert2) 5977 ddb%eig2dval(2,index,iband,ikpt)=d2eig(2,iband,ikpt,idir1,ipert1,idir2,ipert2) 5978 end if 5979 end do !idir1 5980 end do !pert1 5981 end do !idir2 5982 end do !pert2 5983 end do !band 5984 end do !kpt 5985 5986 end subroutine ddb_set_d2eig_reshape
m_ddb/ddb_set_d2matr [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_d2matr
FUNCTION
Set values for the second-order derivative matrix.
INPUTS
iblok=index of the block being set. d2matr=the second-order derivative matrix. flg=flag to indicate presence of a given element.
OUTPUT
SOURCE
777 subroutine ddb_set_d2matr(ddb, iblok, d2matr, flg) 778 779 !Arguments ------------------------------- 780 class(ddb_type),intent(inout) :: ddb 781 !scalars 782 integer,intent(in) :: iblok 783 !array 784 real(dp), intent(in) :: d2matr(2,3,ddb%mpert,3,ddb%mpert) 785 integer, intent(in) :: flg(3,ddb%mpert,3,ddb%mpert) 786 787 !Local variables ------------------------- 788 !scalars 789 integer :: idir1,idir2,ii,ipert1,ipert2 790 791 ! ************************************************************************ 792 793 ii=0 794 do ipert2=1,ddb%mpert 795 do idir2=1,3 796 do ipert1=1,ddb%mpert 797 do idir1=1,3 798 ii=ii+1 799 ddb%flg(ii,iblok) = flg(idir1,ipert1,idir2,ipert2) 800 ddb%val(1,ii,iblok) = d2matr(1,idir1,ipert1,idir2,ipert2) 801 ddb%val(2,ii,iblok) = d2matr(2,idir1,ipert1,idir2,ipert2) 802 end do 803 end do 804 end do 805 end do 806 807 end subroutine ddb_set_d2matr
m_ddb/ddb_set_d3matr [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_d3matr
FUNCTION
Set values for the third-order derivative matrix.
INPUTS
iblok=index of the block we are setting. d2matr=the third-order derivative matrix. flg=flag to indicate presence of a given element. lw=whether this type of perturbation correspond to longwave derivatives
OUTPUT
SOURCE
5684 subroutine ddb_set_d3matr(ddb, iblok, d3matr, flg, lw) 5685 5686 !Arguments ------------------------------- 5687 !array 5688 class(ddb_type),intent(inout) :: ddb 5689 real(dp),intent(in) :: d3matr(2,3,ddb%mpert,3,ddb%mpert,3,ddb%mpert) 5690 integer,intent(in) :: flg(3,ddb%mpert,3,ddb%mpert,3,ddb%mpert) 5691 !scalars 5692 integer,intent(in) :: iblok 5693 logical,intent(in),optional :: lw 5694 5695 !Local variables ------------------------- 5696 !scalars 5697 integer :: idir1,idir2,idir3,ipert1,ipert2,ipert3,index,mpert 5698 5699 ! ************************************************************************ 5700 5701 mpert = ddb%mpert 5702 5703 ! GA: Should be consistent among all ddb_set_dxmatr routines 5704 ! and alway have options to specify block type... 5705 ddb%typ(iblok) = BLKTYP_d3E_xx 5706 if (present(lw)) then 5707 if (lw) then 5708 ddb%typ(iblok) = BLKTYP_d3E_lw 5709 end if 5710 end if 5711 5712 do ipert1=1,mpert 5713 do idir1=1,3 5714 do ipert2=1,mpert 5715 do idir2=1,3 5716 do ipert3=1,mpert 5717 do idir3=1,3 5718 5719 index = idir1 + 3*((ipert1-1)+mpert*((idir2-1) + & 5720 & 3*((ipert2-1)+mpert*((idir3-1) + 3*(ipert3-1))))) 5721 5722 ddb%flg(index,iblok) = flg(idir1,ipert1,idir2,ipert2,idir3,ipert3) 5723 ddb%val(:,index,iblok)= d3matr(:,idir1,ipert1,idir2,ipert2,idir3,ipert3) 5724 5725 end do 5726 end do 5727 end do 5728 end do 5729 end do 5730 end do 5731 5732 5733 end subroutine ddb_set_d3matr
m_ddb/ddb_set_etotal [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_etotal
FUNCTION
Set the total energy
INPUTS
etotal=the total energy. iblok=index of the block we are setting.
OUTPUT
SOURCE
1121 subroutine ddb_set_etotal(ddb, etotal, iblok) 1122 1123 !Arguments ------------------------------- 1124 !array 1125 class(ddb_type),intent(inout) :: ddb 1126 !scalars 1127 real(dp), intent(in) :: etotal 1128 integer,intent(in) :: iblok 1129 1130 ! ************************************************************************ 1131 1132 ddb%typ(iblok) = BLKTYP_d0E_xx 1133 ddb%val(1,1,iblok) = etotal 1134 ddb%val(2,1,iblok) = zero 1135 ddb%flg(1,iblok) = 1 1136 1137 end subroutine ddb_set_etotal
m_ddb/ddb_set_gred [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_gred
FUNCTION
Set the forces in reduced coordinates (Hartree).
INPUTS
gred=the gradient of the total energy with respect to change of reduced coordinates iblok=index of the block being set.
OUTPUT
SOURCE
887 subroutine ddb_set_gred(ddb, gred, iblok) 888 889 !Arguments ------------------------------- 890 !array 891 class(ddb_type),intent(inout) :: ddb 892 real(dp), intent(in) :: gred(3,ddb%natom) 893 !scalars 894 integer,intent(in) :: iblok 895 896 !Local variables ------------------------- 897 !scalars 898 integer :: idir, iatom, indx 899 900 ! ************************************************************************ 901 902 ddb%typ(iblok) = BLKTYP_d1E_xx 903 indx = 0 904 do iatom = 1, ddb%natom 905 do idir = 1, 3 906 indx = indx + 1 907 ddb%flg(indx,iblok) = 1 908 ddb%val(1,indx,iblok) = gred(idir,iatom) 909 ddb%val(2,indx,iblok) = zero 910 end do 911 end do 912 913 end subroutine ddb_set_gred
m_ddb/ddb_set_pel [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_gred
FUNCTION
Set the electronic polarization.
INPUTS
pel=ucvol times the electronic polarization in reduced coordinates. flg=flag to indicate presence of a given element. iblok=index of the block being set.
OUTPUT
SOURCE
934 subroutine ddb_set_pel(ddb, pel, flg, iblok) 935 936 !Arguments ------------------------------- 937 !array 938 class(ddb_type),intent(inout) :: ddb 939 real(dp), intent(in) :: pel(3) 940 integer,intent(in) :: flg(3) 941 !scalars 942 integer,intent(in) :: iblok 943 944 !Local variables ------------------------- 945 !scalars 946 integer :: idir, indx 947 948 ! ************************************************************************ 949 950 ddb%typ(iblok) = BLKTYP_d1E_xx 951 indx = 3*ddb%natom + 3 952 do idir = 1, 3 953 indx = indx + 1 954 ddb%flg(indx,iblok) = flg(idir) 955 ddb%val(1,indx,iblok) = pel(idir) 956 ddb%val(2,indx,iblok) = zero 957 end do 958 959 end subroutine ddb_set_pel
m_ddb/ddb_set_qpt [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_qpt
FUNCTION
Set the q-point wavevector for a certain block. In case of 3rd order derivatives, three q-points need to be specified with the constrain q1 + q2 + q3 = 0.
INPUTS
iblok=index of the block being set. qpt=reduced coordinates of first qpoint qpt2=reduced coordinates of second qpoint qpt3=reduced coordinates of third qpoint
OUTPUT
SOURCE
730 subroutine ddb_set_qpt(ddb, iblok, qpt, qpt2, qpt3) 731 732 !Arguments ------------------------------- 733 !array 734 class(ddb_type),intent(inout) :: ddb 735 real(dp), intent(in) :: qpt(3) 736 real(dp), intent(in),optional :: qpt2(3) 737 real(dp), intent(in),optional :: qpt3(3) 738 !scalars 739 integer,intent(in) :: iblok 740 741 ! ************************************************************************ 742 743 ddb%qpt(1:3,iblok) = qpt(1:3) 744 ddb%nrm(1,iblok) = one 745 746 if (present(qpt2)) then 747 ddb%qpt(4:6,iblok) = qpt2(1:3) 748 ddb%nrm(2,iblok) = one 749 end if 750 751 if (present(qpt3)) then 752 ddb%qpt(7:9,iblok) = qpt3(1:3) 753 ddb%nrm(3,iblok) = one 754 end if 755 756 end subroutine ddb_set_qpt
m_ddb/ddb_set_strten [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_strten
FUNCTION
Set the stress tensor.
INPUTS
strten=the stress tensor in cartesian coordinates. iblok=index of the block we are setting.
OUTPUT
SOURCE
979 subroutine ddb_set_strten(ddb, strten, iblok) 980 981 !Arguments ------------------------------- 982 !array 983 class(ddb_type),intent(inout) :: ddb 984 real(dp), intent(in) :: strten(6) 985 !scalars 986 integer,intent(in) :: iblok 987 988 !Local variables ------------------------- 989 !scalars 990 integer :: indx 991 992 ! ************************************************************************ 993 994 ddb%typ(iblok) = BLKTYP_d1E_xx 995 indx = 3*ddb%natom + 6 996 997 ddb%flg(indx+1:indx+6,1) = 1 998 ddb%val(1,indx+1:indx+6,1) = strten(1:6) 999 ddb%val(2,indx+1:indx+6,1) = zero 1000 1001 end subroutine ddb_set_strten
m_ddb/ddb_set_typ [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_set_typ
FUNCTION
Set the blok typ for one block
INPUTS
iblok: block index typ: type of block
OUTPUT
SOURCE
1218 subroutine ddb_set_typ(ddb, iblok, typ) 1219 1220 !Arguments ------------------------------- 1221 !array 1222 class(ddb_type),intent(inout) :: ddb 1223 !scalars 1224 integer,intent(in) :: iblok,typ 1225 ! ************************************************************************* 1226 1227 ddb%typ(iblok) = typ 1228 1229 end subroutine ddb_set_typ
m_ddb/ddb_symmetrize_and_transform [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_symmetrize_and_transform
FUNCTION
First apply symmetry operations, then transform the second-derivative matrix from reduced coordinates to cartesian coordinates, and also 1) add the ionic part of the effective charges, 2) normalize the electronic dielectric tensor, and add the vacuum polarisation
INPUTS
crystal<type(crystal_t)> iblock=the block index on which to act
SIDE EFFECTS
ddb<type(ddb_type)>=
OUTPUT
SOURCE
4212 subroutine ddb_symmetrize_and_transform(ddb, crystal, iblok) 4213 4214 !Arguments ------------------------------- 4215 !scalars 4216 class(ddb_type),intent(inout) :: ddb 4217 class(crystal_t),intent(in) :: crystal 4218 integer,intent(in) :: iblok 4219 !integer,intent(inout) :: indsym(4,msym,natom) 4220 !integer,intent(out) :: symrec(3,3,msym),symrel(3,3,msym),symafm(msym) 4221 4222 !Local variables------------------------------- 4223 !scalars 4224 integer :: mpert,natom,nsym,ntypat 4225 integer :: nsize,timrev 4226 integer :: i1dir,i1pert,i2dir,i2pert,i3dir,i3pert 4227 !arrays 4228 !integer :: symq(4,2,msym) 4229 integer,allocatable :: symq(:,:,:) 4230 integer,allocatable :: car3flg(:,:,:,:,:,:),carflg(:,:,:,:) 4231 integer,allocatable :: tmpflg(:,:,:,:,:,:),rfpert(:,:,:,:,:,:) 4232 real(dp) :: gprimd(3,3),qpt(3),rprimd(3,3) 4233 real(dp),allocatable :: d2cart(:,:,:,:,:),d3cart(:,:,:,:,:,:,:) 4234 real(dp),allocatable :: tmpval(:,:,:,:,:,:,:) 4235 4236 ! ************************************************************************ 4237 4238 mpert = ddb%mpert 4239 natom = ddb%natom 4240 ntypat = crystal%ntypat 4241 4242 nsym = crystal%nsym 4243 rprimd(:,:) = crystal%rprimd(:,:) 4244 gprimd(:,:) = crystal%gprimd(:,:) 4245 4246 ABI_MALLOC(symq,(4,2,nsym)) 4247 4248 ! Here complete the matrix by symmetrisation of the existing elements 4249 if (ddb%typ(iblok) == BLKTYP_d2E_ns .or. ddb%typ(iblok) == BLKTYP_d2E_st) then 4250 4251 qpt(1)=ddb%qpt(1,iblok)/ddb%nrm(1,iblok) 4252 qpt(2)=ddb%qpt(2,iblok)/ddb%nrm(1,iblok) 4253 qpt(3)=ddb%qpt(3,iblok)/ddb%nrm(1,iblok) 4254 4255 ! Examine the symmetries of the q wavevector 4256 call littlegroup_q(crystal%nsym,qpt,symq,crystal%symrec,crystal%symafm,timrev,prtvol=0) 4257 4258 !GA: Note that d2sym3 and cart29 expect different shapes for tmpflg and tmpval 4259 ! hence the extra dimensions 4260 nsize=3*mpert*3*mpert 4261 ABI_MALLOC(tmpflg,(3,mpert,3,mpert,1,1)) 4262 ABI_MALLOC(tmpval,(2,3,mpert,3,mpert,1,1)) 4263 4264 tmpflg(:,:,:,:,1,1) = reshape(ddb%flg(1:nsize,iblok), shape = (/3,mpert,3,mpert/)) 4265 tmpval(1,:,:,:,:,1,1) = reshape(ddb%val(1,1:nsize,iblok), shape = (/3,mpert,3,mpert/)) 4266 tmpval(2,:,:,:,:,1,1) = reshape(ddb%val(2,1:nsize,iblok), shape = (/3,mpert,3,mpert/)) 4267 4268 ! Then apply symmetry operations 4269 call d2sym3(tmpflg,tmpval,crystal%indsym,mpert,natom,nsym,qpt,symq,crystal%symrec,crystal%symrel,timrev,1) 4270 4271 ! Transform the dynamical matrix in cartesian coordinates 4272 ABI_MALLOC(carflg,(3,mpert,3,mpert)) 4273 ABI_MALLOC(d2cart,(2,3,mpert,3,mpert)) 4274 4275 call cart29(tmpflg,tmpval,carflg,d2cart,gprimd,1,mpert,natom,1,ntypat,rprimd,crystal%typat,crystal%ucvol,crystal%zion) 4276 4277 ddb%flg(1:nsize,iblok) = reshape(carflg,shape = (/3*mpert*3*mpert/)) 4278 ddb%val(1,1:nsize,iblok) = reshape(d2cart(1,:,:,:,:), shape = (/3*mpert*3*mpert/)) 4279 ddb%val(2,1:nsize,iblok) = reshape(d2cart(2,:,:,:,:), shape = (/3*mpert*3*mpert/)) 4280 4281 ABI_FREE(carflg) 4282 ABI_FREE(d2cart) 4283 ABI_FREE(tmpflg) 4284 ABI_FREE(tmpval) 4285 4286 else if (ddb%typ(iblok) == BLKTYP_d3E_xx) then 4287 4288 nsize=3*mpert*3*mpert*3*mpert 4289 ABI_MALLOC(tmpflg,(3,mpert,3,mpert,3,mpert)) 4290 ABI_MALLOC(tmpval,(2,3,mpert,3,mpert,3,mpert)) 4291 ABI_MALLOC(rfpert,(3,mpert,3,mpert,3,mpert)) 4292 4293 tmpflg(:,:,:,:,:,:) = reshape(ddb%flg(1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/)) 4294 tmpval(1,:,:,:,:,:,:) = reshape(ddb%val(1,1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/)) 4295 tmpval(2,:,:,:,:,:,:) = reshape(ddb%val(2,1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/)) 4296 4297 ! Set the elements that are zero by symmetry for raman and 4298 ! non-linear optical susceptibility tensors 4299 rfpert = 0 4300 rfpert(:,natom+2,:,natom+2,:,natom+2) = 1 4301 rfpert(:,1:natom,:,natom+2,:,natom+2) = 1 4302 rfpert(:,natom+2,:,1:natom,:,natom+2) = 1 4303 rfpert(:,natom+2,:,natom+2,:,1:natom) = 1 4304 call sytens(crystal%indsym,mpert,natom,nsym,rfpert,crystal%symrec,crystal%symrel) 4305 do i1pert = 1,mpert 4306 do i2pert = 1,mpert 4307 do i3pert = 1,mpert 4308 do i1dir=1,3 4309 do i2dir=1,3 4310 do i3dir=1,3 4311 if ((rfpert(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)==-2) .and. & 4312 (tmpflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)/=1)) then 4313 tmpval(:,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = zero 4314 tmpflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)=1 4315 end if 4316 end do 4317 end do 4318 end do 4319 end do 4320 end do 4321 end do 4322 4323 call d3sym(tmpflg,tmpval,crystal%indsym,mpert,natom,nsym,crystal%symrec,crystal%symrel) 4324 4325 ABI_MALLOC(d3cart,(2,3,mpert,3,mpert,3,mpert)) 4326 ABI_MALLOC(car3flg,(3,mpert,3,mpert,3,mpert)) 4327 4328 call nlopt(tmpflg,car3flg,tmpval,d3cart,gprimd,mpert,natom,rprimd,crystal%ucvol) 4329 4330 ddb%flg(1:nsize,iblok) = reshape(car3flg, shape = (/3*mpert*3*mpert*3*mpert/)) 4331 ddb%val(1,1:nsize,iblok) = reshape(d3cart(1,:,:,:,:,:,:), shape = (/3*mpert*3*mpert*3*mpert/)) 4332 ddb%val(2,1:nsize,iblok) = reshape(d3cart(2,:,:,:,:,:,:), shape = (/3*mpert*3*mpert*3*mpert/)) 4333 4334 ABI_FREE(d3cart) 4335 ABI_FREE(car3flg) 4336 ABI_FREE(tmpflg) 4337 ABI_FREE(tmpval) 4338 ABI_FREE(rfpert) 4339 4340 else if (ddb%typ(iblok) == BLKTYP_d3E_lw) then 4341 4342 nsize=3*mpert*3*mpert*3*mpert 4343 ABI_MALLOC(tmpflg,(3,mpert,3,mpert,3,mpert)) 4344 ABI_MALLOC(tmpval,(2,3,mpert,3,mpert,3,mpert)) 4345 4346 tmpflg(:,:,:,:,:,:) = reshape(ddb%flg(1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/)) 4347 tmpval(1,:,:,:,:,:,:) = reshape(ddb%val(1,1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/)) 4348 tmpval(2,:,:,:,:,:,:) = reshape(ddb%val(2,1:nsize,iblok), shape = (/3,mpert,3,mpert,3,mpert/)) 4349 4350 ABI_MALLOC(d3cart,(2,3,mpert,3,mpert,3,mpert)) 4351 ABI_MALLOC(car3flg,(3,mpert,3,mpert,3,mpert)) 4352 4353 call lwcart(tmpflg,car3flg,tmpval,d3cart,gprimd,mpert,natom,rprimd) 4354 4355 ddb%flg(1:nsize,iblok) = reshape(car3flg, shape = (/3*mpert*3*mpert*3*mpert/)) 4356 ddb%val(1,1:nsize,iblok) = reshape(d3cart(1,:,:,:,:,:,:), shape = (/3*mpert*3*mpert*3*mpert/)) 4357 ddb%val(2,1:nsize,iblok) = reshape(d3cart(2,:,:,:,:,:,:), shape = (/3*mpert*3*mpert*3*mpert/)) 4358 4359 ABI_FREE(d3cart) 4360 ABI_FREE(car3flg) 4361 ABI_FREE(tmpflg) 4362 ABI_FREE(tmpval) 4363 end if 4364 4365 ABI_FREE(symq) 4366 4367 end subroutine ddb_symmetrize_and_transform
m_ddb/ddb_to_dtset [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_to_dtset
FUNCTION
Initialize a dataset object from ddb. FIXME: I don't understand the goal of this routine. The dtset constructed from the DDB won't be equal to the one used to generate the DDB There's only one safe way to init dtset i.e. from file by calling the parser
INPUTS
OUTPUT
SOURCE
6009 subroutine ddb_to_dtset(comm, dtset, filename, psps) 6010 6011 !Arguments ------------------------------- 6012 integer,intent(in) :: comm 6013 type(dataset_type),intent(inout) :: dtset 6014 type(pseudopotential_type),intent(inout) :: psps 6015 ! type(pawtab_type),intent(inout) :: pawtab(psps%ntypat*psps%usepaw) 6016 character(len=*),intent(in) :: filename 6017 !Local variables ------------------------- 6018 integer :: mxnimage,unddb 6019 !integer :: ii, nn 6020 type(ddb_hdr_type) :: ddb_hdr 6021 6022 ! ************************************************************************ 6023 6024 ABI_UNUSED(psps%usepaw) 6025 6026 !Set variables 6027 mxnimage = 1 ! Only 1 image in the DDB 6028 6029 ! Must read natom from the DDB before being able to allocate some arrays needed for invars9 6030 unddb = get_unit() 6031 call ddb_hdr%open_read(filename,comm=comm) 6032 call ddb_hdr%close() 6033 !close ddb file, just want to read the headers 6034 dtset%ngfft = ddb_hdr%ngfft 6035 6036 ! Copy scalars from ddb 6037 dtset%natom = ddb_hdr%natom 6038 dtset%mband = ddb_hdr%mband 6039 dtset%nkpt = ddb_hdr%nkpt 6040 dtset%nsym = ddb_hdr%msym 6041 dtset%ntypat = ddb_hdr%ntypat 6042 dtset%nspden = ddb_hdr%nspden 6043 dtset%nspinor = ddb_hdr%nspinor 6044 dtset%nsppol = ddb_hdr%nsppol 6045 dtset%occopt = ddb_hdr%occopt 6046 dtset%usepaw = ddb_hdr%usepaw 6047 dtset%intxc = ddb_hdr%intxc 6048 dtset%ixc = ddb_hdr%ixc 6049 dtset%iscf = ddb_hdr%iscf 6050 dtset%dilatmx = ddb_hdr%dilatmx 6051 dtset%ecut = ddb_hdr%ecut 6052 dtset%ecutsm = ddb_hdr%ecutsm 6053 dtset%pawecutdg = ddb_hdr%pawecutdg 6054 dtset%kptnrm = ddb_hdr%kptnrm 6055 dtset%dfpt_sciss = ddb_hdr%dfpt_sciss 6056 dtset%tolwfr = 1.0_dp ! dummy 6057 dtset%tphysel = ddb_hdr%tphysel 6058 dtset%tsmear = ddb_hdr%tsmear 6059 6060 ! Copy arrays from ddb 6061 ABI_REMALLOC(dtset%acell_orig, (3,mxnimage)) 6062 dtset%acell_orig(1:3,1) = ddb_hdr%acell(:) 6063 6064 ABI_REMALLOC(dtset%rprim_orig, (3,3,mxnimage)) 6065 dtset%rprim_orig(1:3,1:3,1) = ddb_hdr%rprim(:,:) 6066 6067 ABI_REMALLOC(dtset%rprimd_orig, (3,3,mxnimage)) 6068 dtset%rprimd_orig(:,1,1) = ddb_hdr%rprim(:,1) * dtset%acell_orig(1,1) 6069 dtset%rprimd_orig(:,2,1) = ddb_hdr%rprim(:,2) * dtset%acell_orig(2,1) 6070 dtset%rprimd_orig(:,3,1) = ddb_hdr%rprim(:,3) * dtset%acell_orig(3,1) 6071 6072 ABI_REMALLOC(dtset%amu_orig,(dtset%ntypat,mxnimage)) 6073 dtset%amu_orig(:,1) = ddb_hdr%amu(:) 6074 6075 ABI_REMALLOC(dtset%typat, (dtset%natom)) 6076 dtset%typat(:) = ddb_hdr%typat(1:ddb_hdr%matom) 6077 6078 ABI_REMALLOC(dtset%spinat, (3,dtset%natom)) 6079 dtset%spinat(:,:) = ddb_hdr%spinat(1:3,1:ddb_hdr%matom) 6080 6081 #ifdef FC_LLVM 6082 ! LLVM 16 doesn't recognize this macro here 6083 ABI_REMALLOC(dtset%xred_orig, (3,dtset%natom,mxnimage) ) 6084 #else 6085 ABI_REMALLOC(dtset%xred_orig, (3,dtset%natom,mxnimage)) 6086 #endif 6087 dtset%xred_orig(:,:,1) = ddb_hdr%xred(1:3,1:ddb_hdr%matom) 6088 6089 ABI_REMALLOC(dtset%ziontypat, (dtset%ntypat)) 6090 dtset%ziontypat(1:ddb_hdr%mtypat) = ddb_hdr%zion(1:ddb_hdr%mtypat) 6091 6092 ABI_REMALLOC(dtset%znucl,(dtset%ntypat)) 6093 dtset%znucl(:) = ddb_hdr%znucl(1:ddb_hdr%mtypat) 6094 6095 ABI_REMALLOC(dtset%nband,(dtset%nkpt)) 6096 dtset%nband(:) = ddb_hdr%nband(1:ddb_hdr%mkpt*ddb_hdr%nsppol) 6097 6098 ABI_REMALLOC(dtset%symafm,(dtset%nsym)) 6099 dtset%symafm(:) = ddb_hdr%symafm(1:ddb_hdr%msym) 6100 6101 ABI_REMALLOC(dtset%symrel, (3,3,dtset%nsym) ) 6102 dtset%symrel(:,:,:) = ddb_hdr%symrel(1:3,1:3,1:ddb_hdr%msym) 6103 6104 ABI_REMALLOC(dtset%tnons,(3,dtset%nsym)) 6105 dtset%tnons(:,:) = ddb_hdr%tnons(1:3,1:ddb_hdr%msym) 6106 6107 ABI_REMALLOC(dtset%kpt,(3,dtset%nkpt)) 6108 dtset%kpt(:,:) = ddb_hdr%kpt(1:3,1:ddb_hdr%mkpt) 6109 6110 ABI_REMALLOC(dtset%wtk,(dtset%nkpt)) 6111 dtset%wtk(:) = ddb_hdr%wtk(1:ddb_hdr%mkpt) 6112 6113 ! GA: I had way too much problems implementing pawtab_copy. 6114 ! The script check-libpaw would report all sorts of errors. 6115 ! Therefore, I do a cheap copy here, copying only the relevant info. 6116 !call pawtab_copy(pawtab, ddb_hdr%pawtab) 6117 ! nn=size(pawtab) 6118 ! if (nn.gt.0) then 6119 ! do ii=1,nn 6120 ! pawtab(ii)%basis_size =ddb_hdr%pawtab(ii)%basis_size 6121 ! pawtab(ii)%lmn_size =ddb_hdr%pawtab(ii)%lmn_size 6122 ! pawtab(ii)%lmn2_size =ddb_hdr%pawtab(ii)%lmn2_size 6123 ! pawtab(ii)%rpaw =ddb_hdr%pawtab(ii)%rpaw 6124 ! pawtab(ii)%rshp =ddb_hdr%pawtab(ii)%rshp 6125 ! pawtab(ii)%shape_type =ddb_hdr%pawtab(ii)%shape_type 6126 ! if (allocated(pawtab(ii)%dij0)) then 6127 ! call alloc_copy(ddb_hdr%pawtab(ii)%dij0, pawtab(ii)%dij0) 6128 ! end if 6129 ! end do 6130 ! end if 6131 6132 call ddb_hdr%free() 6133 6134 end subroutine ddb_to_dtset
m_ddb/ddb_type [ Types ]
NAME
ddb_type
FUNCTION
Provides methods to extract and post-process the results in the derivative database (DDB)
SOURCE
83 type,public :: ddb_type 84 85 logical :: has_ncid_open 86 ! Is currently reading a netcdf file 87 88 integer :: iblock_d2eig_nc 89 ! Is currently reading a netcdf file 90 91 integer :: msize 92 ! Maximum size of dynamical matrices and other perturbations (ddk, dde...) 93 94 integer :: mpert 95 ! Maximum number of perturbations 96 97 integer :: nblok 98 ! Number of 2dte blocks in present object 99 100 integer :: natom 101 ! Number of atoms in the unit cell. 102 103 integer :: ntypat 104 ! Number of type of atoms. 105 106 integer :: occopt 107 ! Occupation option. 108 109 integer :: prtvol 110 ! Verbosity level. 111 112 integer :: nband 113 ! Number of bands for eigenvalues derivatives 114 ! This corresponds to d2eig arrary shape, 115 ! but the actual number of band is nband / nsppol 116 117 integer :: nkpt 118 ! Number of k-points for eigenvalues derivatives 119 120 ! GA: FIXME 121 integer :: nsppol 122 ! Number of spin components for eigenvalues derivatives 123 ! This index is absorbed into nband, to limit array ranks to 7. 124 125 integer :: current_iblok 126 ! Number of k-points for eigenvalues derivatives 127 128 ! These values are used to call the anaddb routines that don't use rprimd, gprimd. 129 real(dp) :: rprim(3,3) 130 real(dp) :: gprim(3,3) 131 real(dp) :: acell(3) 132 133 ! Many of these variables should become private so that one can refactor the ddb_t implementation 134 integer,allocatable :: flg(:,:) 135 ! flg(msize,nblok) 136 ! Flag to indicate presence of a given block 137 138 integer,allocatable :: typ(:) 139 ! typ(nblok) 140 ! Type of each block - nth-order derivatives of energy or eigenvalues. 141 ! (0 => total energy) 142 ! (1=> non-stationary block), 143 ! (2=> stationary block), 144 ! (3=> third order derivative). 145 ! (4 => first-order derivatives of total energy) 146 ! (5 => 2nd-order derivatives of eigenvalues) 147 ! (33 => long wave third order derivatives of total energy) 148 ! (85 => Molecular Berry curvature, 2nd-order derivative) 149 150 real(dp),allocatable :: amu(:) 151 ! amu(ntypat) 152 ! Mass of the atoms (atomic mass unit) 153 154 real(dp),allocatable :: qpt(:,:) 155 ! qpt(9,nblok) 156 ! q-point vector in reciprocal space (reduced lattice coordinates) for each block 157 ! Three possible phonon wavevectors can be specified for 3rd order derivatives, 158 ! but only one should be used in case of second derivative of total energy, 159 ! because we know that the second is the opposite of this value. 160 161 real(dp),allocatable :: nrm(:,:) 162 ! nrm(3,nblok) 163 ! Normalization factors of the wavevectors for each block - can be 0 to indicate a direction of approach to gamma 164 165 real(dp),allocatable :: val(:,:,:) 166 ! val(2,msize,nblok) 167 ! Values of the second energy derivatives in each block 168 169 real(dp),allocatable :: kpt(:,:) 170 ! kpt(3,nkpt) 171 ! k-point vector in reciprocal space for eigenvalues derivatives 172 173 real(dp),allocatable :: eig2dval(:,:,:,:) 174 ! eig2dval(2,msize,nband,nkpt) 175 ! Values of the second derivatives of eigenvalues 176 ! Only a single block (a single q-point) is held in memory. 177 ! Note that isppol index is wrapped into nband index. 178 179 contains 180 181 procedure :: init => ddb_init 182 ! Construct the object from the dtset. 183 184 procedure :: free => ddb_free 185 ! Free dynamic memory. 186 187 procedure :: malloc => ddb_malloc 188 ! Allocate dynamic memory 189 190 procedure :: malloc_d2eig => ddb_malloc_d2eig 191 ! Allocate dynamic memory 192 193 procedure :: copy => ddb_copy 194 ! Copy the object. 195 196 !procedure :: get_qptopt => ddb_get_qptopt 197 198 procedure :: set_qpt => ddb_set_qpt 199 ! Set the wavevector 200 201 procedure :: set_d1matr => ddb_set_d1matr 202 ! Set values for the first-order derivative matrix in tensor shape 203 204 procedure :: get_d1matr => ddb_get_d1matr 205 ! Transform the first-order derivative matrix in tensor shape 206 207 procedure :: set_d2matr => ddb_set_d2matr 208 ! Set values for the second-order derivative matrix 209 210 procedure :: get_d2matr => ddb_get_d2matr 211 ! Transform the second-order derivative matrix in tensor shape 212 213 procedure :: set_d3matr => ddb_set_d3matr 214 ! Set values for the third-order derivative matrix 215 216 procedure :: get_d3matr => ddb_get_d3matr 217 ! Transform the third-order derivative matrix in tensor shape 218 219 procedure :: get_d2eig => ddb_get_d2eig 220 ! Transform the second-order derivative matrix of eigs in tensor shape 221 222 procedure :: set_d2eig => ddb_set_d2eig 223 ! Set values for the second-order derivative matrix of eigs 224 225 procedure :: set_d2eig_reshape => ddb_set_d2eig_reshape 226 ! Set values for the second-order derivative matrix of eigs 227 ! with band index before perturbation indices 228 229 procedure :: set_gred => ddb_set_gred 230 ! Set the gradient of total energy in reduced coordinates 231 232 procedure :: set_pel => ddb_set_pel 233 ! Set the electronic polarization 234 235 procedure :: set_strten => ddb_set_strten 236 ! Set the stress tensor 237 238 procedure :: set_etotal => ddb_set_etotal 239 ! Set the total energy 240 241 procedure :: set_brav => ddb_set_brav 242 ! Set the bravais lattice. 243 244 procedure :: set_typ => ddb_set_typ 245 ! Set the typ of one block 246 247 procedure :: bcast => ddb_bcast 248 ! Broadcast the object. 249 250 procedure :: get_etotal => ddb_get_etotal 251 ! Read the GS total energy. 252 253 procedure :: get_gred => ddb_get_gred 254 ! Get the gradient of total energy in reduced coordinates 255 256 procedure :: get_pel => ddb_get_pel 257 ! Get the electronic polarization 258 259 procedure :: get_strten => ddb_get_strten 260 ! Get the stress tensor 261 262 procedure :: get_dielt_zeff => ddb_get_dielt_zeff 263 ! Reads the Dielectric Tensor and the Effective Charges 264 265 procedure :: get_dielt => ddb_get_dielt 266 ! Reads the Dielectric Tensor 267 268 procedure :: get_quadrupoles => ddb_get_quadrupoles 269 ! Reads the Quadrupoles 270 271 procedure :: get_dchidet => ddb_get_dchidet 272 ! Reads the non-linear optical susceptibility tensor and the 273 ! first-order change in the linear dielectric susceptibility 274 275 procedure :: diagoq => ddb_diagoq 276 ! Compute the phonon frequencies at the specified q-point by performing 277 ! a direct diagonalizatin of the dynamical matrix. 278 279 procedure :: get_asrq0 => ddb_get_asrq0 280 ! Return object used to enforce the acoustic sum rule 281 282 procedure :: symmetrize_and_transform => ddb_symmetrize_and_transform 283 ! Symmetrize, transform cartesian coordinates, and add missing components 284 285 procedure :: write_block_txt => ddb_write_block_txt 286 ! Writes blocks of data in the DDB in text format. 287 288 procedure :: write => ddb_write 289 ! Write the DDB file in either txt or netcdf format. 290 291 procedure :: write_txt => ddb_write_txt 292 ! Write the body of the DDB text file. 293 294 procedure :: write_nc => ddb_write_nc 295 ! Write the netcdf file (DDB.nc). 296 297 procedure :: read_block_txt => ddb_read_block_txt 298 ! Read blocks of data in the DDB. 299 300 procedure :: get_block => ddb_get_block 301 ! Finds the block containing the derivatives of the total energy. 302 303 procedure :: read_d2eig => ddb_read_d2eig 304 ! Read the next DDB block containing 2nd order derivatives of eigenvalues. 305 306 procedure :: read_d2eig_txt => ddb_read_d2eig_txt 307 ! Read the next DDB block containing 2nd order derivatives of eigenvalues. 308 309 procedure :: read_d2eig_nc => ddb_read_d2eig_nc 310 ! Read the next DDB block containing 2nd order derivatives of eigenvalues. 311 312 procedure :: write_d2eig => ddb_write_d2eig 313 ! Read the current DDB block containing 2nd order derivatives of eigenvalues. 314 315 procedure :: write_d2eig_txt => ddb_write_d2eig_txt 316 ! Read the current DDB block containing 2nd order derivatives of eigenvalues. 317 318 procedure :: write_d2eig_nc => ddb_write_d2eig_nc 319 ! Write the current DDB block containing 2nd order derivatives of eigenvalues. 320 321 procedure :: read_d0E_nc => ddb_read_d0E_nc 322 ! Read the next DDB block containing 0th order derivatives of energy. 323 324 procedure :: read_d1E_nc => ddb_read_d1E_nc 325 ! Read the next DDB block containing 1st order derivatives of energy. 326 327 procedure :: read_d2E_nc => ddb_read_d2E_nc 328 ! Read the next DDB block containing 2nd order derivatives of energy. 329 330 procedure :: read_d3E_nc => ddb_read_d3E_nc 331 ! Read the next DDB block containing 3rd order derivatives of energy. 332 333 procedure :: from_file => ddb_from_file 334 ! Construct the object from the DDB file. 335 336 procedure :: read_txt => ddb_read_txt 337 ! Construct the object from the DDB file in text format. 338 339 procedure :: read_nc => ddb_read_nc 340 ! Construct the object from the DDB file in netcdf format. 341 342 procedure :: can_merge_blocks => ddb_can_merge_blocks 343 ! Tell if two blocks can be merged 344 345 procedure :: merge_blocks => ddb_merge_blocks 346 ! Merge a block of an other ddb to the current object. 347 348 end type ddb_type 349 350 public :: ddb_to_dtset ! Transfer ddb_hdr to dtset datatype 351 public :: merge_ddb ! Read a list of ddb files and merge them into a single ddb object
m_ddb/ddb_write [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_write
FUNCTION
Write the DDB file in either txt or netcdf format.
INPUTS
ddb_hdr=ddb header object. filename=name of the file being written (abo_DS*_DDB) with_psps 1-> include information on pseudopoentials 0-> do not include information on pseudopoentials comm=MPI communicator
SOURCE
4773 subroutine ddb_write(ddb, ddb_hdr, filename, with_psps, comm) 4774 4775 !Arguments ------------------------------- 4776 class(ddb_type),intent(inout) :: ddb 4777 type(ddb_hdr_type),intent(inout) :: ddb_hdr 4778 character(len=fnlen),intent(in) :: filename 4779 integer,intent(in),optional :: with_psps 4780 integer,intent(in),optional :: comm 4781 4782 !Local variables------------------------------- 4783 character(len=fnlen) :: filename_ 4784 integer :: iomode 4785 4786 ! ************************************************************************ 4787 4788 call ddb_hdr%get_iomode(filename, 2, iomode, filename_) 4789 4790 if (iomode==IO_MODE_ETSF) then 4791 call ddb%write_nc(ddb_hdr, filename_, comm=comm, with_psps=with_psps) 4792 else if (iomode==IO_MODE_FORTRAN) then 4793 call ddb%write_txt(ddb_hdr, filename_, with_psps=with_psps, comm=comm) 4794 ddb_hdr%mpert = ddb%mpert ! Text format doesnt know about mpert. 4795 end if 4796 4797 end subroutine ddb_write
m_ddb/ddb_write_block_txt [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_write_block_txt
FUNCTION
This routine writes blocks of data in the DDB in text format.
INPUTS
choice= (2 => write), (3 => write minimal info ) mpert =maximum number of ipert msize=maximum size of the arrays flags and values nunit=unit number for the data block file
OUTPUT
(see side effects)
SIDE EFFECTS
Input/Output ddb = ddb block datastructure ddb%typ=type of the block: 0 => total energy 1 => second-order energy derivatives, non-stationary block 2 => second-order energy derivatives, stationary block 3 => third-order energy derivatives 4 => first-order energy derivatives: forces, stresses and polarization 5 => second-order eigenvalue derivatives ddb%flg(msize)=flag for every matrix element (0=> the element is not in the data block), (1=> the element is in the data blok) ddb%qpt(9)=wavevector of the perturbation(s). The elements from 1 to 3 are used if we are dealing with the 2nd derivative of total energy (only one wavevector), while all elements are used in case of a third order derivative of total energy (three wavevector could be present) ddb%nrm(3)=normalization factors for the three allowed wavevectors. ddb%val(2,msize)=real(dp), complex, value of the matrix elements that are present in the data block blkval2(2,msize,mband,nkpt) = value of the matrix elements that are present in a block of EIGR2D/EIGI2D
NOTES
only executed by one processor.
SOURCE
4587 subroutine ddb_write_block_txt(ddb,iblok,choice,mband,mpert,msize,nkpt,nunit,& 4588 blkval2,kpt) !optional 4589 4590 !Arguments ------------------------------- 4591 !scalars 4592 integer,intent(in) :: choice,mband,mpert,msize,nkpt,nunit 4593 integer,intent(in) :: iblok 4594 class(ddb_type),intent(in) :: ddb 4595 !arrays 4596 real(dp),intent(in),optional :: kpt(3,nkpt) 4597 real(dp),intent(in),optional :: blkval2(2,msize,mband,nkpt) 4598 4599 !Local variables ------------------------- 4600 !scalars 4601 integer :: iband,idir1,idir2,idir3,ii,ikpt,ipert1,ipert2,ipert3 4602 integer :: nelmts 4603 logical :: eig2d_ 4604 4605 ! ********************************************************************* 4606 4607 ! GA: Remove choice option. 4608 ! choice=3 is used to write summary info at the end of the DDB. 4609 ! With MG and MV, we agreed that it could be removed. 4610 4611 ! GA: Remove arguments: mband, blkval2, kpt 4612 ! This feature of writing eigenvalues 2nd deriv is no longer used 4613 ! (see 80_tdep/m_tdep_abitypes.F90) 4614 ! With FB, we agreed that it could be removed. 4615 4616 eig2d_ = .false. 4617 if(present(blkval2).and.present(kpt)) eig2d_ = .true. 4618 4619 4620 ! Count the number of elements 4621 nelmts=0 4622 do ii=1,msize 4623 if(ddb%flg(ii,iblok)==1)nelmts=nelmts+1 4624 end do 4625 4626 ! Write the block type and number of elements 4627 write(nunit,*)' ' 4628 if (ddb%typ(iblok) == BLKTYP_d0E_xx) then 4629 write(nunit, '(a,i12)' )' Total energy - # elements :',nelmts 4630 else if (ddb%typ(iblok)==BLKTYP_d2E_ns) then 4631 write(nunit, '(a,i12)' )' 2nd derivatives (non-stat.) - # elements :',nelmts 4632 else if(ddb%typ(iblok)==BLKTYP_d2E_st) then 4633 write(nunit, '(a,i12)' )' 2nd derivatives (stationary) - # elements :',nelmts 4634 else if(ddb%typ(iblok)==BLKTYP_d2E_mbc) then 4635 write(nunit, '(a,i12)' )' 2nd derivatives (MBC) - # elements :',nelmts 4636 else if(ddb%typ(iblok)==BLKTYP_d3E_xx) then 4637 write(nunit, '(a,i12)' )' 3rd derivatives - # elements :',nelmts 4638 else if (ddb%typ(iblok) == BLKTYP_d1E_xx) then 4639 write(nunit, '(a,i12)' )' 1st derivatives - # elements :',nelmts 4640 else if (ddb%typ(iblok) == BLKTYP_d2eig_re) then 4641 write(nunit, '(a,i12)' )' 2nd eigenvalue derivatives - # elements :',nelmts 4642 else if(ddb%typ(iblok)==BLKTYP_d3E_lw) then 4643 write(nunit, '(a,i12)' )' 3rd derivatives (long wave) - # elements :',nelmts 4644 end if 4645 4646 ! Write the 2nd derivative block 4647 if (is_type_d2E(ddb%typ(iblok))) then 4648 4649 ! Write the phonon wavevector 4650 write(nunit, '(a,3es16.8,f6.1)' )' qpt',(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok) 4651 4652 ! Write the matrix elements 4653 if(choice==2)then 4654 ii=0 4655 do ipert2=1,mpert 4656 do idir2=1,3 4657 do ipert1=1,mpert 4658 do idir1=1,3 4659 ii=ii+1 4660 if(ddb%flg(ii,iblok)==1)then 4661 write(nunit,'(4i4,2d22.14)') idir1, ipert1, idir2, ipert2, & 4662 ddb%val(1,ii,iblok),ddb%val(2,ii,iblok) 4663 end if 4664 end do 4665 end do 4666 end do 4667 end do 4668 end if 4669 4670 4671 else if (is_type_d3E(ddb%typ(iblok))) then 4672 ! Write the 3rd derivative block 4673 4674 ! Write the phonon wavevectors 4675 write(nunit, '(a,3es16.8,f6.1)' )' qpt',(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok) 4676 write(nunit, '(a,3es16.8,f6.1)' )' ',(ddb%qpt(ii,iblok),ii=4,6),ddb%nrm(2,iblok) 4677 write(nunit, '(a,3es16.8,f6.1)' )' ',(ddb%qpt(ii,iblok),ii=7,9),ddb%nrm(3,iblok) 4678 4679 ! Write the matrix elements 4680 if(choice==2)then 4681 ii=0 4682 do ipert3=1,mpert 4683 do idir3=1,3 4684 do ipert2=1,mpert 4685 do idir2=1,3 4686 do ipert1=1,mpert 4687 do idir1=1,3 4688 ii=ii+1 4689 if(ddb%flg(ii,iblok)==1)then 4690 write(nunit, '(6i6,2d22.14)' )& 4691 idir1,ipert1,idir2,ipert2,idir3,ipert3,ddb%val(1,ii,iblok),ddb%val(2,ii,iblok) 4692 end if 4693 end do 4694 end do 4695 end do 4696 end do 4697 end do 4698 end do 4699 end if 4700 4701 4702 else if (is_type_d0E(ddb%typ(iblok))) then 4703 ! Write total energy 4704 if (choice == 2) write(nunit,'(2d22.14)')ddb%val(1,1,iblok),ddb%val(2,1,iblok) 4705 4706 else if (is_type_d1E(ddb%typ(iblok))) then 4707 ! Write the 1st derivative blok 4708 if (choice == 2) then 4709 ii = 0 4710 do ipert1 = 1, mpert 4711 do idir1 = 1, 3 4712 ii = ii + 1 4713 if (ddb%flg(ii,iblok) == 1) then 4714 write(nunit,'(2i6,2d22.14)')idir1,ipert1,ddb%val(1,ii,iblok),ddb%val(2,ii,iblok) 4715 end if 4716 end do 4717 end do 4718 end if 4719 4720 else if (is_type_d2eig(ddb%typ(iblok))) then 4721 ! Write the phonon wavevector 4722 write(nunit, '(a,3es16.8,f6.1)' )' qpt',(ddb%qpt(ii,iblok),ii=1,3),ddb%nrm(1,iblok) 4723 ! Write the matrix elements 4724 ! GA: Note that isppol is invisible here. It is simply marked as more bands. 4725 ! To be changed in a future version of text format. 4726 if(choice==2)then 4727 if (eig2d_) then 4728 do ikpt=1,nkpt 4729 write(nunit,'(a,3es16.8)')' K-point:',(kpt(ii,ikpt),ii=1,3) 4730 do iband=1,mband 4731 write(nunit,'(a,i3)')' Band:',iband 4732 ii=0 4733 do ipert2=1,mpert 4734 do idir2=1,3 4735 do ipert1=1,mpert 4736 do idir1=1,3 4737 ii=ii+1 4738 if(ddb%flg(ii,iblok)==1)then 4739 write(nunit,'(4i4,2d22.14)')idir1,ipert1,idir2,ipert2,blkval2(1,ii,iband,ikpt),blkval2(2,ii,iband,ikpt) 4740 end if 4741 end do !idir1 4742 end do !ipert1 4743 end do !idir2 4744 end do !ipert2 4745 end do !iband 4746 end do !ikpt 4747 end if !eig2d_ 4748 end if !choice 4749 end if !ddb%typ(iblok) 4750 4751 end subroutine ddb_write_block_txt
m_ddb/ddb_write_d2eig [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_write_d2eig
FUNCTION
Write the current eig2d data as the next block in the ddb file.
INPUTS
ddb_hdr=ddb header object. unddb=unit of the open ddb file in text format or netcdf identifier.
SOURCE
4865 subroutine ddb_write_d2eig(ddb, ddb_hdr, iblok, comm) 4866 !Arguments ------------------------------- 4867 class(ddb_type),intent(inout) :: ddb 4868 type(ddb_hdr_type),intent(inout) :: ddb_hdr 4869 integer,intent(in) :: iblok 4870 integer,intent(in),optional :: comm 4871 4872 !Local variables ------------------------- 4873 !scalars 4874 integer,parameter :: master=0 4875 character(len=500) :: msg 4876 4877 ! ************************************************************************ 4878 4879 if (present(comm)) then 4880 if (xmpi_comm_rank(comm) /= master) return 4881 end if 4882 4883 if (ddb_hdr%has_open_file_nc) then 4884 4885 call ddb%write_d2eig_nc(ddb_hdr%ncid, iblok) 4886 4887 else if (ddb_hdr%has_open_file_txt) then 4888 4889 call ddb%write_d2eig_txt(ddb_hdr%unddb, iblok) 4890 4891 else 4892 write(msg, '(3a)' )& 4893 ! File has not been opened by ddb_hdr 4894 'Attempting to write into unopen DDB file.',ch10,& 4895 'Action: contact Abinit group.' 4896 ABI_ERROR(msg) 4897 end if 4898 4899 end subroutine ddb_write_d2eig
m_ddb/ddb_write_d2eig_nc [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_write_d2eig_nc
FUNCTION
Write the current d2eig data in the ddb netcdf file.
INPUTS
iblok=index of the eig2d block within the d2eig subgroup. ncid=netcdf identifier of a file open in writing mode. comm=MPI communicator.
SOURCE
4918 subroutine ddb_write_d2eig_nc(ddb, ncid, iblok, comm) 4919 !Arguments ------------------------------- 4920 class(ddb_type),intent(inout) :: ddb 4921 integer,intent(in) :: ncid 4922 integer,intent(in) :: iblok 4923 integer,intent(in),optional :: comm 4924 4925 !Local variables ------------------------- 4926 !scalars 4927 integer,parameter :: master=0 4928 integer :: iband, jband, bandshift, isppol, mband 4929 integer :: ikpt, ipert1, idir1, ipert2, idir2, ii 4930 integer :: ncid_d2eig, ncerr 4931 real(dp) :: qpt(3) 4932 real(dp), allocatable :: matrix_d2eig(:,:,:,:,:,:,:) 4933 real(dp), allocatable :: matrix_d2eig_isppol(:,:,:,:,:,:,:) 4934 integer, allocatable :: flg_d2eig(:,:,:,:) 4935 4936 ! ************************************************************************ 4937 4938 4939 if (present(comm)) then 4940 if (xmpi_comm_rank(comm) /= master) return 4941 end if 4942 4943 ncid_d2eig = nctk_idgroup(ncid, 'd2eig') 4944 4945 qpt(1:3) = ddb%qpt(1:3,iblok) 4946 ncerr = nf90_put_var(ncid_d2eig, nctk_idname(ncid_d2eig,& 4947 'reduced_coordinates_of_qpoints'),& 4948 qpt,& 4949 start=[1,iblok]) 4950 NCF_CHECK(ncerr) 4951 ncerr = nf90_put_var(ncid_d2eig, nctk_idname(ncid_d2eig,& 4952 'qpoints_normalization'),& 4953 ddb%nrm(1,iblok),& 4954 start=[iblok]) 4955 NCF_CHECK(ncerr) 4956 4957 ! GA: Here we assume that all blocks are d2eig blocks. 4958 ! Otherwise, iblok is only the 'local' iblok index 4959 ! and we would need to figure out the corresponding 'global' index 4960 call ddb%get_d2eig(matrix_d2eig, flg_d2eig, iblok) 4961 4962 mband = ddb%nband / ddb%nsppol 4963 ABI_MALLOC(matrix_d2eig_isppol, (2,3,ddb%mpert,3,ddb%mpert,mband,ddb%nkpt)) 4964 4965 ! Loop over spin index 4966 do isppol=1,ddb%nsppol 4967 4968 bandshift = (isppol - 1) * mband 4969 4970 do iband=1,mband 4971 jband = bandshift + iband 4972 4973 do ikpt=1,ddb%nkpt 4974 do ipert1=1,ddb%mpert 4975 do idir1=1,3 4976 do ipert2=1,ddb%mpert 4977 do idir2=1,3 4978 do ii=1,2 4979 matrix_d2eig_isppol(ii,idir2,ipert2,idir1,ipert1,iband,ikpt)=& 4980 matrix_d2eig(ii,idir2,ipert2,idir1,ipert1,jband,ikpt) 4981 end do 4982 end do 4983 end do 4984 end do 4985 end do 4986 end do 4987 4988 4989 end do ! iband 4990 4991 ncerr = nf90_put_var(ncid_d2eig, nctk_idname(ncid_d2eig,& 4992 'matrix_values'),& 4993 matrix_d2eig_isppol,& 4994 start=[1,1,1,1,1,1,1,isppol,iblok]) 4995 !count=[2,3,ddb%mpert,3,ddb%mpert,ddb%nband,ddb%nkpt,1,1]) 4996 !count=[2,3,ddb%mpert,3,ddb%mpert,ddb%nkpt,ddb%nband,1,1]) 4997 NCF_CHECK(ncerr) 4998 4999 end do ! isppol 5000 5001 ncerr = nf90_put_var(ncid_d2eig, nctk_idname(ncid_d2eig,& 5002 'matrix_mask'),& 5003 flg_d2eig,& 5004 start=[1,1,1,1,iblok]) 5005 NCF_CHECK(ncerr) 5006 5007 ABI_SFREE(matrix_d2eig_isppol) 5008 ABI_SFREE(matrix_d2eig) 5009 ABI_SFREE(flg_d2eig) 5010 5011 end subroutine ddb_write_d2eig_nc
m_ddb/ddb_write_d2eig_txt [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_write_d2eig_txt
FUNCTION
Write the eig2d data as the next block in text file format.
INPUTS
ddb_hdr=ddb header object. unddb=unit of the open ddb file in text format.
SOURCE
5031 subroutine ddb_write_d2eig_txt(ddb, unddb, iblok) 5032 !Arguments ------------------------------- 5033 class(ddb_type),intent(in) :: ddb 5034 integer,intent(in) :: unddb 5035 integer,intent(in) :: iblok 5036 5037 !Local variables ------------------------- 5038 !scalars 5039 integer,parameter :: iblok_eig2d=1 5040 integer,parameter :: choice=2 5041 5042 ! ************************************************************************ 5043 5044 ! GA: This routine is redundant with outbsd. 5045 ! The present implementation should replace outbsd. 5046 5047 call ddb%write_block_txt(iblok,choice,ddb%nband,ddb%mpert,ddb%msize,ddb%nkpt,unddb,& 5048 ddb%eig2dval(:,:,:,:), ddb%kpt(:,:)) 5049 5050 end subroutine ddb_write_d2eig_txt
m_ddb/ddb_write_nc [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_write_nc
FUNCTION
Write the netndf file DDB.nc in the format of version 20230219.
INPUTS
ddb_hdr=ddb header object with open file. filename=DDB filename. comm=MPI communicator. with_psps 1-> include information on pseudopoentials 0-> do not include information on pseudopoentials
SOURCE
5072 subroutine ddb_write_nc(ddb, ddb_hdr, filename, comm, with_psps) 5073 5074 !Arguments ------------------------------- 5075 class(ddb_type),intent(inout) :: ddb 5076 type(ddb_hdr_type),intent(inout) :: ddb_hdr 5077 character(len=*),intent(in) :: filename 5078 integer,intent(in),optional :: comm 5079 integer,intent(in),optional :: with_psps 5080 5081 !Local variables ------------------------- 5082 !scalars 5083 integer,parameter :: master=0 5084 integer :: ncid, ncerr, ncid_d0E, ncid_d1E, ncid_d2E, ncid_d3E, ncid_d2eig 5085 integer :: ii,iblok,iblok_d0E,iblok_d1E,iblok_d2E,iblok_d3E,iblok_d2eig 5086 !arrays 5087 integer,allocatable :: flg_d1E(:,:) 5088 integer,allocatable :: flg_d2E(:,:,:,:) 5089 integer,allocatable :: flg_d3E(:,:,:,:,:,:) 5090 real(dp) :: qpt(3), qpts(3,3), nrms(3) 5091 real(dp),allocatable :: matrix_d1E(:,:,:) 5092 real(dp),allocatable :: matrix_d2E(:,:,:,:,:) 5093 real(dp),allocatable :: matrix_d3E(:,:,:,:,:,:,:) 5094 5095 ! ************************************************************************ 5096 5097 if (present(comm)) then 5098 if (xmpi_comm_rank(comm) /= master) return 5099 end if 5100 5101 #ifdef HAVE_NETCDF 5102 5103 ! ===================== 5104 ! Header and dimensions 5105 ! ===================== 5106 ! Copy types and dimensions into the header 5107 ddb_hdr%mpert = ddb%mpert 5108 call ddb_hdr%set_typ(ddb%nblok, ddb%typ) 5109 5110 call ddb_hdr%open_write_nc(filename, with_psps=with_psps) 5111 ncid = ddb_hdr%ncid 5112 5113 ! Get all group id 5114 ncid_d0E = nctk_idgroup(ncid, 'd0E') 5115 ncid_d1E = nctk_idgroup(ncid, 'd1E') 5116 ncid_d2E = nctk_idgroup(ncid, 'd2E') 5117 ncid_d3E = nctk_idgroup(ncid, 'd3E') 5118 ncid_d2eig = nctk_idgroup(ncid, 'd2eig') 5119 5120 ! ============================= 5121 ! Loop over block to be written 5122 ! ============================= 5123 5124 iblok_d0E = 0; iblok_d1E = 0; iblok_d2E = 0; iblok_d3E = 0; iblok_d2eig = 0 5125 5126 do iblok=1,ddb%nblok 5127 5128 ! ------------------------ 5129 ! Zeroth-order derivatives 5130 ! ------------------------ 5131 if (is_type_d0E(ddb%typ(iblok))) then 5132 5133 iblok_d0E = iblok_d0E + 1 5134 5135 ncerr = nf90_put_var(ncid_d0E, nctk_idname(ncid_d0E,& 5136 'matrix_values'),& 5137 ddb%val(1,1,iblok),& 5138 start=[iblok_d0E]) 5139 NCF_CHECK(ncerr) 5140 5141 ncerr = nf90_put_var(ncid_d0E, nctk_idname(ncid_d0E,& 5142 'matrix_mask'),& 5143 ddb%flg(1,iblok),& 5144 start=[iblok_d0E]) 5145 NCF_CHECK(ncerr) 5146 5147 ! ----------------------- 5148 ! First-order derivatives 5149 ! ----------------------- 5150 else if (is_type_d1E(ddb%typ(iblok))) then 5151 5152 iblok_d1E = iblok_d1E + 1 5153 5154 call ddb%get_d1matr(iblok, matrix_d1E, flg_d1E) 5155 5156 ncerr = nf90_put_var(ncid_d1E, nctk_idname(ncid_d1E,& 5157 'matrix_values'),& 5158 matrix_d1E,& 5159 start=[1,1,1,iblok_d1E]) 5160 NCF_CHECK(ncerr) 5161 5162 ncerr = nf90_put_var(ncid_d1E, nctk_idname(ncid_d1E,& 5163 'matrix_mask'),& 5164 flg_d1E,& 5165 start=[1,1,iblok_d1E]) 5166 NCF_CHECK(ncerr) 5167 ABI_SFREE(matrix_d1E) 5168 ABI_SFREE(flg_d1E) 5169 5170 ! ------------------------ 5171 ! Second-order derivatives 5172 ! ------------------------ 5173 else if (is_type_d2E(ddb%typ(iblok))) then 5174 5175 iblok_d2E = iblok_d2E + 1 5176 5177 do ii=1,3 5178 qpt(ii) = ddb%qpt(ii,iblok) 5179 end do 5180 ncerr = nf90_put_var(ncid_d2E, nctk_idname(ncid_d2E,& 5181 'reduced_coordinates_of_qpoints'),& 5182 qpt,& 5183 start=[1,iblok_d2E]) 5184 NCF_CHECK(ncerr) 5185 5186 ncerr = nf90_put_var(ncid_d2E, nctk_idname(ncid_d2E,& 5187 'qpoints_normalization'),& 5188 (ddb%nrm(1,iblok)),& 5189 start=[iblok_d2E]) 5190 NCF_CHECK(ncerr) 5191 5192 call ddb%get_d2matr(iblok, matrix_d2E, flg_d2E) 5193 5194 ncerr = nf90_put_var(ncid_d2E, nctk_idname(ncid_d2E,& 5195 'matrix_values'),& 5196 matrix_d2E,& 5197 start=[1,1,1,1,1,iblok_d2E]) 5198 NCF_CHECK(ncerr) 5199 5200 ncerr = nf90_put_var(ncid_d2E, nctk_idname(ncid_d2E,& 5201 'matrix_mask'),& 5202 flg_d2E,& 5203 start=[1,1,1,1,iblok_d2E]) 5204 NCF_CHECK(ncerr) 5205 ABI_SFREE(matrix_d2E) 5206 ABI_SFREE(flg_d2E) 5207 5208 ! ----------------------- 5209 ! Third-order derivatives 5210 ! ----------------------- 5211 else if (is_type_d3E(ddb%typ(iblok))) then 5212 5213 iblok_d3E = iblok_d3E + 1 5214 5215 do ii=1,3 5216 nrms(ii) = ddb%nrm(ii,iblok) 5217 qpts(1,ii) = ddb%qpt(ii,iblok) 5218 qpts(2,ii) = ddb%qpt(ii+3,iblok) 5219 qpts(3,ii) = ddb%qpt(ii+6,iblok) 5220 end do 5221 5222 ncerr = nf90_put_var(ncid_d3E, nctk_idname(ncid_d3E,& 5223 'reduced_coordinates_of_qpoints'),& 5224 qpts,& 5225 start=[1,1,iblok_d3E]) 5226 NCF_CHECK(ncerr) 5227 5228 ncerr = nf90_put_var(ncid_d3E, nctk_idname(ncid_d3E,& 5229 'qpoints_normalization'),& 5230 nrms,& 5231 start=[1,iblok_d3E]) 5232 NCF_CHECK(ncerr) 5233 5234 call ddb%get_d3matr(iblok, matrix_d3E, flg_d3E) 5235 5236 ncerr = nf90_put_var(ncid_d3E, nctk_idname(ncid_d3E,& 5237 'matrix_values'),& 5238 matrix_d3E,& 5239 start=[1,1,1,1,1,1,1,iblok_d3E]) 5240 NCF_CHECK(ncerr) 5241 5242 ncerr = nf90_put_var(ncid_d3E, nctk_idname(ncid_d3E,& 5243 'matrix_mask'),& 5244 flg_d3E,& 5245 start=[1,1,1,1,1,1,iblok_d3E]) 5246 NCF_CHECK(ncerr) 5247 5248 ABI_SFREE(matrix_d3E) 5249 ABI_SFREE(flg_d3E) 5250 5251 ! --------------------------------------- 5252 ! Second-order derivatives of eigenvalues 5253 ! --------------------------------------- 5254 else if (is_type_d2eig(ddb%typ(iblok))) then 5255 5256 iblok_d2eig = iblok_d2eig + 1 5257 5258 call ddb%write_d2eig_nc(ncid_d2eig, iblok_d2eig) 5259 5260 end if 5261 end do 5262 5263 #else 5264 ABI_ERROR("NETCDF support required to write DDB.nc file.") 5265 #endif 5266 5267 end subroutine ddb_write_nc
m_ddb/ddb_write_txt [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
ddb_write_txt
FUNCTION
Write the DDB file in text format.
INPUTS
ddb_hdr=ddb header object. filename=name of the file being written (abo_DS*_DDB) with_psps 1-> include information on pseudopoentials 0-> do not include information on pseudopoentials
SOURCE
4818 subroutine ddb_write_txt(ddb, ddb_hdr, filename, with_psps, comm) 4819 4820 !Arguments ------------------------------- 4821 class(ddb_type),intent(inout) :: ddb 4822 type(ddb_hdr_type),intent(inout) :: ddb_hdr 4823 character(len=*),intent(in) :: filename 4824 integer,intent(in),optional :: with_psps 4825 integer,intent(in),optional :: comm 4826 4827 !Local variables ------------------------- 4828 !scalars 4829 integer :: iblok 4830 integer,parameter :: master=0, choice=2 4831 4832 ! ************************************************************************ 4833 4834 if (present(comm)) then 4835 if (xmpi_comm_rank(comm) /= master) return 4836 end if 4837 4838 call ddb_hdr%open_write_txt(filename, with_psps) 4839 4840 do iblok=1,ddb%nblok 4841 call ddb%write_block_txt(iblok,choice,1,ddb%mpert,ddb%msize,ddb_hdr%nkpt,ddb_hdr%unddb) 4842 end do 4843 4844 call ddb_hdr%close() 4845 4846 end subroutine ddb_write_txt
m_ddb/dtchi [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
dtchi
FUNCTION
Reads the non-linear optical susceptibility tensor and the first-order change in the linear dielectric susceptibility induced by an atomic displacement in the Gamma Block coming from the Derivative Data Base (third-order derivatives).
INPUTS
blkval(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies natom= number of atoms in unit cell mpert =maximum number of ipert ramansr= if /= 0, impose sum rule on first-order derivatives of the electronic susceptibility with respect to atomic displacements nlflag= if =3, only the non-linear optical susceptibilities is computed
OUTPUT
dchide(3,3,3) = non-linear optical coefficients dchidt(natom,3,3,3) = first-order change of the electronic dielectric tensor induced by an individual atomic displacement
SOURCE
3333 subroutine dtchi(blkval,dchide,dchidt,mpert,natom,ramansr,nlflag) 3334 3335 !Arguments ------------------------------- 3336 !scalars 3337 integer,intent(in) :: mpert,natom,ramansr,nlflag 3338 !arrays 3339 real(dp),intent(in) :: blkval(2,3*mpert*3*mpert*3*mpert) 3340 real(dp),intent(out) :: dchide(3,3,3),dchidt(natom,3,3,3) 3341 3342 !Local variables ------------------------- 3343 !scalars 3344 integer :: depl,elfd1,elfd2,elfd3,iatom,ivoigt 3345 logical :: iwrite 3346 real(dp) :: wttot 3347 !arrays 3348 integer :: voigtindex(6,2) 3349 real(dp) :: d3cart(2,3,mpert,3,mpert,3,mpert),dvoigt(3,6),sumrule(3,3,3) 3350 real(dp) :: wghtat(natom) 3351 3352 ! ********************************************************************* 3353 3354 d3cart(1,:,:,:,:,:,:) = reshape(blkval(1,:),shape = (/3,mpert,3,mpert,3,mpert/)) 3355 d3cart(2,:,:,:,:,:,:) = reshape(blkval(2,:),shape = (/3,mpert,3,mpert,3,mpert/)) 3356 3357 ! Extraction of non-linear optical coefficients 3358 do elfd1 = 1,3 3359 do elfd2 = 1,3 3360 do elfd3 = 1,3 3361 dchide(elfd1,elfd2,elfd3) = d3cart(1,elfd1,natom+2,elfd2,natom+2,elfd3,natom+2) 3362 end do 3363 end do 3364 end do 3365 3366 ! Transform to Voigt notations 3367 voigtindex(:,1) = (/1,2,3,2,1,1/) 3368 voigtindex(:,2) = (/1,2,3,3,3,2/) 3369 do ivoigt = 1, 6 3370 elfd2 = voigtindex(ivoigt,1) 3371 elfd3 = voigtindex(ivoigt,2) 3372 do elfd1 = 1, 3 3373 dvoigt(elfd1,ivoigt) = 0.5_dp*(dchide(elfd1,elfd2,elfd3) + dchide(elfd1,elfd3,elfd2)) 3374 end do 3375 end do 3376 3377 ! Transform to pm/V 3378 dvoigt(:,:) = dvoigt(:,:)*16*(pi**2)*(Bohr_Ang**2)*1.0d-8*eps0/e_Cb 3379 3380 ! Extraction of $\frac{d \chi}{d \tau}$ 3381 if (nlflag < 3) then 3382 do iatom = 1, natom 3383 do depl = 1,3 3384 do elfd1 = 1,3 3385 do elfd2 = 1,3 3386 dchidt(iatom,depl,elfd1,elfd2) = d3cart(1,depl,iatom,elfd1,natom+2,elfd2,natom+2) 3387 end do 3388 end do 3389 end do 3390 end do 3391 end if 3392 3393 wghtat(:) = zero 3394 if (ramansr == 1) then 3395 wghtat(:) = one/dble(natom) 3396 3397 else if (ramansr == 2) then 3398 3399 wttot = zero 3400 do iatom = 1, natom 3401 do depl = 1,3 3402 do elfd1 = 1,3 3403 do elfd2 = 1,3 3404 wghtat(iatom) = wghtat(iatom) + abs(dchidt(iatom,depl,elfd1,elfd2)) 3405 end do 3406 end do 3407 end do 3408 wttot = wttot + wghtat(iatom) 3409 end do 3410 3411 wghtat(:) = wghtat(:)/wttot 3412 end if 3413 3414 iwrite = ab_out > 0 3415 3416 if (iwrite) then 3417 write(ab_out,*)ch10 3418 write(ab_out,*)'Non-linear optical coefficients d (pm/V)' 3419 write(ab_out,'(6f12.6)')dvoigt(1,:) 3420 write(ab_out,'(6f12.6)')dvoigt(2,:) 3421 write(ab_out,'(6f12.6)')dvoigt(3,:) 3422 end if 3423 3424 if (ramansr /= 0) then 3425 if (iwrite) then 3426 write(ab_out,*)ch10 3427 write(ab_out,*)'The violation of the Raman sum rule' 3428 write(ab_out,*)'by the first-order electronic dielectric tensors ','is as follows' 3429 write(ab_out,*)' atom' 3430 write(ab_out,*)' displacement' 3431 end if 3432 3433 sumrule(:,:,:) = zero 3434 do elfd2 = 1,3 3435 do elfd1 = 1,3 3436 do depl = 1,3 3437 do iatom = 1, natom 3438 sumrule(depl,elfd1,elfd2) = sumrule(depl,elfd1,elfd2) + dchidt(iatom,depl,elfd1,elfd2) 3439 end do 3440 do iatom = 1, natom 3441 dchidt(iatom,depl,elfd1,elfd2) = dchidt(iatom,depl,elfd1,elfd2) - wghtat(iatom)*sumrule(depl,elfd1,elfd2) 3442 end do 3443 end do 3444 end do 3445 end do 3446 3447 if (iwrite) then 3448 do depl = 1,3 3449 write(ab_out,'(6x,i2,3(3x,f16.9))') depl,sumrule(depl,1,1:3) 3450 write(ab_out,'(8x,3(3x,f16.9))') sumrule(depl,2,1:3) 3451 write(ab_out,'(8x,3(3x,f16.9))') sumrule(depl,3,1:3) 3452 write(ab_out,*) 3453 end do 3454 end if 3455 end if ! ramansr 3456 3457 if (nlflag < 3) then 3458 if (iwrite) then 3459 write(ab_out,*)ch10 3460 write(ab_out,*)' First-order change in the electronic dielectric ' 3461 write(ab_out,*)' susceptibility tensor (Bohr^-1)' 3462 write(ab_out,*)' induced by an atomic displacement' 3463 if (ramansr /= 0) then 3464 write(ab_out,*)' (after imposing the sum over all atoms to vanish)' 3465 end if 3466 write(ab_out,*)' atom displacement' 3467 3468 do iatom = 1,natom 3469 do depl = 1,3 3470 write(ab_out,'(1x,i4,9x,i2,3(3x,f16.9))')iatom,depl,dchidt(iatom,depl,1,:) 3471 write(ab_out,'(16x,3(3x,f16.9))')dchidt(iatom,depl,2,:) 3472 write(ab_out,'(16x,3(3x,f16.9))')dchidt(iatom,depl,3,:) 3473 end do 3474 3475 write(ab_out,*) 3476 end do 3477 end if 3478 end if 3479 3480 end subroutine dtchi
m_ddb/dtech9 [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
dtech9
FUNCTION
Reads the Dielectric Tensor and the Effective Charges in the Gamma Block coming from the Derivative Data Base.
INPUTS
natom= number of atoms in unit cell iblok= index of the Gamma block mpert =maximum number of ipert nblok= number of blocks in the DDB blkval(2,3*mpert*3*mpert,nblok)= dynamical matrices In our case, the nblok is restricted to iblok [unit]=Output unit number
OUTPUT
zeff(3,3,natom)=effective charge on each atom, versus electric field and atomic displacement. Note the following convention: zeff(electric field direction, atomic direction, atom index) dielt(3,3)=dielectric tensor
SOURCE
3250 subroutine dtech9(blkval,dielt,iblok,mpert,natom,nblok,zeff,unit) 3251 3252 !Arguments ------------------------------- 3253 !scalars 3254 integer,intent(in) :: iblok,mpert,natom,nblok 3255 integer,intent(in),optional :: unit 3256 !arrays 3257 real(dp),intent(in) :: blkval(2,3,mpert,3,mpert,nblok) 3258 real(dp),intent(out) :: dielt(3,3),zeff(3,3,natom) 3259 3260 !Local variables ------------------------- 3261 !scalars 3262 integer :: depl,elec,elec1,elec2,iatom, unt 3263 character(len=1000) :: msg 3264 3265 ! ********************************************************************* 3266 3267 unt = std_out; if (present(unit)) unt = unit 3268 3269 ! Extraction of effectives charges 3270 do iatom=1,natom 3271 do elec=1,3 3272 do depl=1,3 3273 zeff(elec,depl,iatom)=0.5*& 3274 (blkval(1,depl,iatom,elec,natom+2,iblok)+& 3275 blkval(1,elec,natom+2,depl,iatom,iblok)) 3276 end do 3277 end do 3278 end do 3279 3280 ! Extraction of dielectric tensor 3281 do elec1=1,3 3282 do elec2=1,3 3283 dielt(elec1,elec2)=blkval(1,elec1,natom+2,elec2,natom+2,iblok) 3284 end do 3285 end do 3286 3287 write(msg,'(a,3es16.6,3es16.6,3es16.6)' )' Dielectric Tensor ',& 3288 dielt(1,1),dielt(1,2),dielt(1,3),& 3289 dielt(2,1),dielt(2,2),dielt(2,3),& 3290 dielt(3,1),dielt(3,2),dielt(3,3) 3291 call wrtout(unt, msg) 3292 3293 call wrtout(unt, ' Effectives Charges ') 3294 do iatom=1,natom 3295 write(msg,'(a,i4,3es16.6,3es16.6,3es16.6)' )' atom ',iatom,& 3296 zeff(1,1,iatom),zeff(1,2,iatom),zeff(1,3,iatom),& 3297 zeff(2,1,iatom),zeff(2,2,iatom),zeff(2,3,iatom),& 3298 zeff(3,1,iatom),zeff(3,2,iatom),zeff(3,3,iatom) 3299 call wrtout(unt, msg) 3300 end do 3301 3302 end subroutine dtech9
m_ddb/dtqdrp [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
dtqdrp
FUNCTION
Reads the Dynamical Quadrupole or the P^(1) Tensor in the Gamma Block coming from the Derivative Data Base (long wave third-order derivatives).
INPUTS
blkval(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies ddb_version = 8 digit integer giving date. To mantain compatibility with olderDDB files. lwsym = 0 do not symmetrize the tensor wrt efield and qvec derivative |-> 1st gradient of polarization response to atomic displacement = 1 symmetrize the tensor wrt efield and qvec derivative |-> dynamic quadrupoles natom= number of atoms in unit cell mpert =maximum number of ipert
OUTPUT
lwtens(3,3,3,natom) = Dynamical Quadrupoles or P^(1) tensor
SOURCE
6582 subroutine dtqdrp(blkval,ddb_version,lwsym,mpert,natom,lwtens) 6583 6584 !Arguments ------------------------------- 6585 !scalars 6586 integer,intent(in) :: ddb_version,lwsym,mpert,natom 6587 !arrays 6588 real(dp),intent(in) :: blkval(2,3*mpert*3*mpert*3*mpert) 6589 real(dp),intent(out) :: lwtens(3,3,3,natom) 6590 6591 !Local variables ------------------------- 6592 !scalars 6593 integer,parameter :: cvrsio8=20100401 6594 integer :: elfd,iatd,iatom,qvecd 6595 real(dp) :: fac 6596 logical :: iwrite 6597 character(len=500) :: msg 6598 !arrays 6599 real(dp) :: d3cart(2,3,mpert,3,mpert,3,mpert) 6600 6601 ! ********************************************************************* 6602 6603 d3cart(1,:,:,:,:,:,:) = reshape(blkval(1,:),shape = (/3,mpert,3,mpert,3,mpert/)) 6604 d3cart(2,:,:,:,:,:,:) = reshape(blkval(2,:),shape = (/3,mpert,3,mpert,3,mpert/)) 6605 6606 !Define a factor to apply if DDB file has been created with the old version of 6607 !the longwave driver. 6608 if (ddb_version <= cvrsio8) then 6609 fac=-two 6610 else 6611 fac=one 6612 end if 6613 6614 !Extraction of quadrupoles (need symmetrization wrt qvecd and elfd) 6615 do iatom = 1,natom 6616 do iatd = 1,3 6617 do elfd = 1,3 6618 do qvecd = 1,elfd-1 6619 if (lwsym==1) then 6620 lwtens(elfd,qvecd,iatd,iatom) = fac * & 6621 (d3cart(2,elfd,natom+2,iatd,iatom,qvecd,natom+8)+d3cart(2,qvecd,natom+2,iatd,iatom,elfd,natom+8)) 6622 lwtens(qvecd,elfd,iatd,iatom) = lwtens(elfd,qvecd,iatd,iatom) 6623 else if (lwsym==0) then 6624 lwtens(elfd,qvecd,iatd,iatom) = fac * d3cart(2,elfd,natom+2,iatd,iatom,qvecd,natom+8) 6625 lwtens(qvecd,elfd,iatd,iatom) = fac * d3cart(2,qvecd,natom+2,iatd,iatom,elfd,natom+8) 6626 end if 6627 end do 6628 if (lwsym==1) then 6629 lwtens(elfd,elfd,iatd,iatom) = fac * two*d3cart(2,elfd,natom+2,iatd,iatom,elfd,natom+8) 6630 else if (lwsym==0) then 6631 lwtens(elfd,elfd,iatd,iatom) = fac * d3cart(2,elfd,natom+2,iatd,iatom,elfd,natom+8) 6632 end if 6633 end do 6634 end do 6635 end do 6636 6637 iwrite = ab_out > 0 6638 6639 if (iwrite) then 6640 if (lwsym==1) then 6641 write(msg,*)' atom dir Qxx Qyy Qzz Qyz Qxz Qxy' 6642 call wrtout([ab_out,std_out],msg) 6643 do iatom= 1, natom 6644 write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iatom, 'x',lwtens(1,1,1,iatom),lwtens(2,2,1,iatom),lwtens(3,3,1,iatom), & 6645 & lwtens(2,3,1,iatom),lwtens(1,3,1,iatom),lwtens(1,2,1,iatom) 6646 call wrtout([ab_out,std_out],msg) 6647 write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iatom, 'y',lwtens(1,1,2,iatom),lwtens(2,2,2,iatom),lwtens(3,3,2,iatom), & 6648 & lwtens(2,3,2,iatom),lwtens(1,3,2,iatom),lwtens(1,2,2,iatom) 6649 call wrtout([ab_out,std_out],msg) 6650 write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iatom, 'z',lwtens(1,1,3,iatom),lwtens(2,2,3,iatom),lwtens(3,3,3,iatom), & 6651 & lwtens(2,3,3,iatom),lwtens(1,3,3,iatom),lwtens(1,2,3,iatom) 6652 call wrtout([ab_out,std_out],msg) 6653 end do 6654 else if (lwsym==0) then 6655 write(msg,*) & 6656 & ' atom dir Pxx Pyy Pzz Pyz Pxz Pxy Pzy Pzx Pyx' 6657 call wrtout([ab_out,std_out],msg) 6658 do iatom= 1, natom 6659 write(msg,'(2x,i3,3x,a3,2x,9f12.6)') iatom, 'x',lwtens(1,1,1,iatom),lwtens(2,2,1,iatom),lwtens(3,3,1,iatom), & 6660 & lwtens(2,3,1,iatom),lwtens(1,3,1,iatom),lwtens(1,2,1,iatom), & 6661 & lwtens(3,2,1,iatom),lwtens(3,1,1,iatom),lwtens(2,1,1,iatom) 6662 call wrtout([ab_out,std_out],msg) 6663 write(msg,'(2x,i3,3x,a3,2x,9f12.6)') iatom, 'y',lwtens(1,1,2,iatom),lwtens(2,2,2,iatom),lwtens(3,3,2,iatom), & 6664 & lwtens(2,3,2,iatom),lwtens(1,3,2,iatom),lwtens(1,2,2,iatom), & 6665 & lwtens(3,2,2,iatom),lwtens(3,1,2,iatom),lwtens(2,1,2,iatom) 6666 call wrtout([ab_out,std_out],msg) 6667 write(msg,'(2x,i3,3x,a3,2x,9f12.6)') iatom, 'z',lwtens(1,1,3,iatom),lwtens(2,2,3,iatom),lwtens(3,3,3,iatom), & 6668 & lwtens(2,3,3,iatom),lwtens(1,3,3,iatom),lwtens(1,2,3,iatom), & 6669 & lwtens(3,2,3,iatom),lwtens(3,1,3,iatom),lwtens(2,1,3,iatom) 6670 call wrtout([ab_out,std_out],msg) 6671 end do 6672 endif 6673 end if 6674 6675 end subroutine dtqdrp
m_ddb/gamma9 [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
gamma9
FUNCTION
This small routine checks if the wavevector qphon and the corresponding normalisation factor represent a phonon at Gamma.
INPUTS
qphon(3)=wavevector qphnrm=normalisation factor qtol=tolerance
OUTPUT
gamma= if 1, means that the wavevector is indeed at Gamma otherwise 0.
SOURCE
1595 subroutine gamma9(gamma,qphon,qphnrm,qtol) 1596 1597 !Arguments ------------------------------- 1598 !scalars 1599 integer,intent(out) :: gamma 1600 real(dp),intent(in) :: qphnrm,qtol 1601 !arrays 1602 real(dp),intent(in) :: qphon(3) 1603 1604 ! ********************************************************************* 1605 1606 if( (abs(qphon(1))<qtol .and. abs(qphon(2))<qtol .and. abs(qphon(3))<qtol) .or. abs(qphnrm)<qtol ) then 1607 gamma=1 1608 else 1609 gamma=0 1610 end if 1611 1612 end subroutine gamma9
m_ddb/lwcart [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
lwcart
FUNCTION
Transform the 3rd-order energy derivative read from the ddb file generated by a long wave calculation into cartesian coordinates, and also...
INPUTS
blkflg(3,mpert,3,mpert,3,mpert)= ( 1 if the element of the 3dte has been calculated ; 0 otherwise ) d3(2,3,mpert,3,mpert,3,mpert)= matrix of the 3DTE gprimd(3,3)=dimensional primitive translations for reciprocal space(bohr^-1) mpert =maximum number of ipert natom= number of atoms rprimd(3,3)=dimensional primitive translations (bohr)
OUTPUT
carflg(3,mpert,3,mpert,3,mpert)=1 if the element of d3cart has been calculated, 0 otherwise d3cart(2,3,mpert,3,mpert,3,mpert)=matrix of third-order energy derivatives in cartesian coordinates
SOURCE
6484 subroutine lwcart(blkflg,carflg,d3,d3cart,gprimd,mpert,natom,rprimd) 6485 6486 !Arguments ------------------------------- 6487 !scalars 6488 integer,intent(in) :: mpert,natom 6489 !arrays 6490 integer,intent(in) :: blkflg(3,mpert,3,mpert,3,mpert) 6491 integer,intent(out) :: carflg(3,mpert,3,mpert,3,mpert) 6492 real(dp),intent(in) :: d3(2,3,mpert,3,mpert,3,mpert),gprimd(3,3),rprimd(3,3) 6493 real(dp),intent(out) :: d3cart(2,3,mpert,3,mpert,3,mpert) 6494 6495 !Local variables ------------------------- 6496 !scalars 6497 integer :: i1dir,i1pert,i2dir,i2pert,i3dir,i3pert 6498 integer :: ii 6499 !arrays 6500 integer :: flg1(3),flg2(3) 6501 real(dp) :: vec1(3),vec2(3) 6502 6503 ! ******************************************************************* 6504 6505 !Transform to cartesian coordinates 6506 d3cart(:,:,:,:,:,:,:) = d3(:,:,:,:,:,:,:) 6507 carflg(:,:,:,:,:,:) = 0 6508 6509 do i1pert = 1, mpert 6510 do i2pert = 1, mpert 6511 do i3pert = 1, mpert 6512 6513 do i2dir = 1, 3 6514 do i3dir = 1, 3 6515 do ii= 1, 2 6516 vec1(:) = d3cart(ii,:,i1pert,i2dir,i2pert,i3dir,i3pert) 6517 flg1(:) = blkflg(:,i1pert,i2dir,i2pert,i3dir,i3pert) 6518 call cart39(flg1,flg2,gprimd,i1pert,natom,rprimd,vec1,vec2) 6519 d3cart(ii,:,i1pert,i2dir,i2pert,i3dir,i3pert) = vec2(:) 6520 carflg(:,i1pert,i2dir,i2pert,i3dir,i3pert) = flg2(:) 6521 end do 6522 end do 6523 end do 6524 6525 do i1dir = 1, 3 6526 do i3dir = 1, 3 6527 do ii= 1, 2 6528 vec1(:) = d3cart(ii,i1dir,i1pert,:,i2pert,i3dir,i3pert) 6529 flg1(:) = blkflg(i1dir,i1pert,:,i2pert,i3dir,i3pert) 6530 call cart39(flg1,flg2,gprimd,i2pert,natom,rprimd,vec1,vec2) 6531 d3cart(ii,i1dir,i1pert,:,i2pert,i3dir,i3pert) = vec2(:) 6532 carflg(i1dir,i1pert,:,i2pert,i3dir,i3pert) = flg2(:) 6533 end do 6534 end do 6535 end do 6536 6537 do i1dir = 1, 3 6538 do i2dir = 1, 3 6539 do ii= 1, 2 6540 vec1(:) = d3cart(ii,i1dir,i1pert,i2dir,i2pert,:,i3pert) 6541 flg1(:) = blkflg(i1dir,i1pert,i2dir,i2pert,:,i3pert) 6542 call cart39(flg1,flg2,gprimd,i3pert,natom,rprimd,vec1,vec2) 6543 d3cart(ii,i1dir,i1pert,i2dir,i2pert,:,i3pert) = vec2(:) 6544 carflg(i1dir,i1pert,i2dir,i2pert,:,i3pert) = flg2(:) 6545 end do 6546 end do 6547 end do 6548 6549 end do 6550 end do 6551 end do 6552 6553 end subroutine lwcart
m_ddb/merge_ddb [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
merge_ddb
FUNCTION
Read a list of ddb files and merge them into a single ddb object.
INPUTS
nddb=number of DDBs to merge filenames=names of input DDB files outfile=name of the merged DDB file to be written dscrpt=string description of the final ddb. chkopt=option for consistency checks between DDB files (0 --> do not check header consistency between files) (1 --> check header consistency between files)
OUTPUT
SOURCE
6159 subroutine merge_ddb(nddb, filenames, outfile, dscrpt, chkopt) 6160 6161 !Arguments ------------------------------- 6162 !scalars 6163 integer,intent(in) :: nddb 6164 integer,intent(in) :: chkopt 6165 !arrays 6166 character(len=fnlen),intent(in) :: filenames(nddb) 6167 character(len=fnlen),intent(in) :: outfile, dscrpt 6168 6169 !Local variables ------------------------- 6170 !scalars 6171 integer,parameter :: master=0 6172 integer :: iddb, iddb_mkpt, iddb_psps 6173 integer :: dimekb, matom, mband, mblok, mkpt, nsppol 6174 integer :: mtypat, lmnmax, usepaw, mblktyp, msym 6175 integer :: msize, msize_, mpert 6176 integer :: nblok, iblok, iblok1, iblok2 6177 integer :: comm 6178 logical :: eig2d, can_merge 6179 integer,parameter :: prtvol=0 6180 character(len=500) :: msg 6181 type(ddb_type) :: ddb, ddb2 6182 type(ddb_hdr_type) :: ddb_hdr, ddb_hdr2 6183 type(crystal_t) :: crystal 6184 6185 ! ************************************************************************ 6186 6187 comm = xmpi_world 6188 6189 ! ----------------------------------------------- 6190 ! Read all headers and evaluate arrays dimensions 6191 ! ----------------------------------------------- 6192 if (xmpi_comm_rank(comm) == master) then 6193 call wrtout(std_out, sjoin(ch10, " merge_ddb: Reading all headers.")) 6194 end if 6195 6196 dimekb=0 ; matom=0 ; mband=0 ; mblok=0 ; mkpt=0 ; mpert=0 6197 msize=0 ; mtypat=0 ; lmnmax=0 ; usepaw=0 ; mblktyp=1 6198 iddb_mkpt = 1 ; iddb_psps = nddb 6199 msym=192 6200 6201 eig2d = .False. 6202 do iddb=1,nddb 6203 6204 call ddb_hdr%open_read(filenames(iddb), comm, dimonly=1) 6205 6206 matom=max(matom,ddb_hdr%matom) 6207 6208 ! GA: Should get mkpt from the ddb containing d2eig, if any. 6209 ! In facts, since I removed comparison on the k-points 6210 ! in ddb_hdr_compare, I should add a check to make sure 6211 ! k-points are consistent when merging d2eig data. 6212 if (ddb_hdr%mkpt > mkpt) then 6213 mkpt = ddb_hdr%mkpt 6214 iddb_mkpt = iddb 6215 end if 6216 !mkpt=max(mkpt,ddb_hdr%mkpt) 6217 mtypat=max(mtypat,ddb_hdr%mtypat) 6218 msym=max(msym,ddb_hdr%msym) 6219 mband=max(mband,ddb_hdr%mband) 6220 dimekb=max(dimekb,ddb_hdr%psps%dimekb) 6221 lmnmax=max(lmnmax,ddb_hdr%psps%lmnmax) 6222 usepaw=max(usepaw,ddb_hdr%usepaw) 6223 nsppol = ddb_hdr%nsppol 6224 6225 ! Count the blocks 6226 mblok=mblok+ddb_hdr%nblok 6227 6228 ! Figure out if we are merging eig2d files 6229 if (is_type_d2eig(ddb_hdr%mblktyp)) then 6230 eig2d = .True. 6231 end if 6232 6233 ! Figure out if we are merging d3E blocks and compute msize accordingly 6234 mpert = max(mpert,ddb_hdr%mpert) 6235 msize_ = 3 * mpert * 3 * mpert 6236 if (is_type_d3E(ddb_hdr%mblktyp)) msize_ = msize_ * 3 * mpert 6237 msize = max(msize, msize_) 6238 6239 if (ddb_hdr%with_psps>0 .or. ddb_hdr%psps%usepaw > 0) then 6240 iddb_psps = iddb 6241 end if 6242 6243 end do 6244 6245 ddb%nsppol = nsppol 6246 6247 ! --------------- 6248 ! Allocate arrays 6249 ! --------------- 6250 if (eig2d) then 6251 ! GA: We need to multiply mband by nsppol (to keep array rank below 8) 6252 call ddb%malloc(msize, mblok, matom, mtypat, mpert, mkpt, mband * nsppol) 6253 else 6254 call ddb%malloc(msize, mblok, matom, mtypat, mpert) 6255 end if 6256 6257 ! ------------------------------------------------------- 6258 ! Initialize the output ddb_hdr using the first input ddb 6259 ! ------------------------------------------------------- 6260 6261 ! GA: The last ddb is usually the one that contains the most info on pseudos 6262 ! however, we should check them all and figure out which one has 6263 ! the most info. 6264 6265 call ddb_hdr%free() ! GA: why do I need this? Try to remove 6266 call ddb_hdr%open_read(filenames(1), comm, & 6267 matom=matom,mtypat=mtypat,mband=mband,mkpt=mkpt,& 6268 msym=msym,dimekb=dimekb,lmnmax=lmnmax,usepaw=usepaw) 6269 call ddb_hdr%close() 6270 ddb_hdr%mpert = mpert 6271 ddb_hdr%msize = msize 6272 6273 ! GA: We are setting mkpt at initialization, 6274 ! but netcdf file declares dimension with nkpt. 6275 ! TODO: Should check consistency of nkpt 6276 ! among of all blocks containing eig2d data. 6277 6278 ! ================== 6279 ! Read all databases 6280 ! ================== 6281 6282 nblok = 0 6283 6284 do iddb=1,nddb 6285 6286 ! Open the corresponding input DDB, and read the database file information 6287 write(msg, '(a,a,i6)' )ch10,' read the input derivative database number',iddb 6288 call wrtout(std_out,msg) 6289 6290 ! Note: it is necessary to specify mkpt, otherwise the comparison will crash 6291 call ddb_hdr2%open_read(filenames(iddb), comm, & 6292 matom=matom,mtypat=mtypat,mband=mband,mkpt=mkpt,& 6293 msym=msym,dimekb=dimekb,lmnmax=lmnmax,usepaw=usepaw) 6294 call ddb_hdr2%close() 6295 6296 if (chkopt==1)then 6297 6298 ! Compare the current DDB and input DDB information. 6299 ! In case of an inconsistency, halt the execution. 6300 call wrtout(std_out, ' compare the current and input DDB information') 6301 6302 6303 ! GA: Maybe the problem is that we are comparing uninitialized pawtab 6304 call ddb_hdr%compare(ddb_hdr2) 6305 6306 else 6307 ! No comparison between the current DDB and input DDB information. 6308 call wrtout(std_out,msg) 6309 write(msg, '(3a)' )& 6310 'No comparison/check is performed for the current and input DDB information ',ch10,& 6311 'because argument --nostrict was passed to the command line. ' 6312 ABI_COMMENT(msg) 6313 end if 6314 6315 if (chkopt==1 .or. usepaw==1) then 6316 call ddb_hdr%copy_missing_variables(ddb_hdr2) 6317 end if 6318 6319 ! GA: In principle, this could be done only once, 6320 ! but I could not managed to do that without failing test v8[07]. 6321 if (iddb == iddb_psps) then 6322 call ddb_hdr%copy_psps_from(ddb_hdr2) 6323 end if 6324 6325 call ddb_hdr2%free() 6326 6327 ! Now read the whole DDB 6328 call ddb2%from_file(filenames(iddb), ddb_hdr2, crystal, comm, prtvol, raw=1) 6329 call crystal%free() 6330 call ddb_hdr2%free() 6331 6332 ! -------------------------------------------------------------- 6333 ! Double loop over the blocks of the last ddb and the output ddb 6334 ! -------------------------------------------------------------- 6335 6336 do iblok2=1,ddb2%nblok 6337 6338 can_merge = .false. 6339 do iblok1=1, nblok 6340 6341 can_merge = ddb%can_merge_blocks(ddb2, iblok1, iblok2) 6342 6343 if (can_merge) then 6344 write(msg, '(a,i5,a,a)' )' merge block #',iblok2,' from file ', filenames(iddb) 6345 call wrtout(std_out,msg) 6346 iblok = iblok1 ! Merge with previous block 6347 exit 6348 end if 6349 end do 6350 6351 if (.not. can_merge) then 6352 write(msg, '(a,i5,a,a)' )' add block #',iblok2,' from file ', filenames(iddb) 6353 call wrtout(std_out,msg) 6354 nblok = nblok + 1 6355 iblok = nblok 6356 end if 6357 6358 call ddb%merge_blocks(ddb2, iblok, iblok2) 6359 6360 end do ! iblok2 6361 6362 ! Free memory 6363 call ddb2%free() 6364 6365 end do ! iddb 6366 6367 6368 6369 ddb_hdr%nblok = nblok 6370 ddb%nblok = nblok 6371 ddb_hdr%dscrpt = dscrpt 6372 6373 call ddb_hdr%set_typ(ddb%nblok, ddb%typ) 6374 6375 ddb_hdr%mpert = mpert ! This is done anyway at writing 6376 6377 ! Summarize the merging phase 6378 write(msg, '(a,i6,a)' )' Final DDB has ',nblok,' blocks.' 6379 call wrtout(std_out,msg) 6380 6381 ! Always use format specified with output filename. 6382 ! GA: Might need an extra variable to enforce a different iomode 6383 ddb_hdr%iomode = iomode_from_fname(outfile) 6384 6385 ! GA: This is because netcdf format has more info than txt 6386 ! and psps might be initialized even if with_psps==0 6387 ! Very weird that I have to do this. 6388 ! TODO Do not enforce with_psps=1. Change the test reference instead. 6389 if (ddb_hdr%iomode/=IO_MODE_ETSF) then 6390 if (ddb_hdr%with_psps==0) then 6391 ddb_hdr%psps%dimekb = 0 6392 ddb_hdr%psps%lmnmax = 0 6393 ABI_SFREE(ddb_hdr%psps%ekb) 6394 ABI_SFREE(ddb_hdr%psps%indlmn) 6395 ABI_MALLOC(ddb_hdr%psps%ekb,(ddb_hdr%psps%dimekb,ddb_hdr%mtypat)) 6396 ABI_MALLOC(ddb_hdr%psps%indlmn,(6,ddb_hdr%psps%lmnmax,ddb_hdr%mtypat)) 6397 ddb_hdr%psps%ekb = zero 6398 ddb_hdr%psps%indlmn = zero 6399 end if 6400 end if 6401 6402 ! Enforce full initialization, regardless of DDB content 6403 ddb_hdr%with_psps=1 6404 ddb_hdr%with_dfpt_vars=1 6405 6406 ! Write the final ddb to file. 6407 if (.not. eig2d) then 6408 call ddb%write(ddb_hdr, outfile) 6409 end if 6410 6411 ! ================================= 6412 ! Second derivatives of eigenvalues 6413 ! ================================= 6414 if (eig2d) then 6415 6416 ! GA: Here we assume that the blocks are complete wrt perturbations. 6417 ! No merging of blocks occurs. 6418 ! TODO: Implement merging of partial d2eig blocks 6419 6420 ddb%kpt(:,:) = ddb_hdr%kpt(:,:) 6421 6422 ! Open the output DDB and write the header 6423 call ddb_hdr%open_write(outfile, with_psps=1, comm=comm) 6424 6425 iblok = 0 6426 do iddb=1,nddb 6427 6428 call ddb_hdr2%open_read(filenames(iddb), comm, & 6429 matom=matom,mtypat=mtypat,mband=mband,mkpt=mkpt,& 6430 msym=msym,dimekb=dimekb,lmnmax=lmnmax,usepaw=usepaw) 6431 6432 do iblok2=1,ddb_hdr2%nblok 6433 6434 ! Handle one block at a time 6435 iblok = iblok + 1 6436 call ddb%read_d2eig(ddb_hdr2, iblok, iblok2) 6437 call ddb%write_d2eig(ddb_hdr, iblok) 6438 6439 end do 6440 6441 call ddb_hdr2%close() ! Close the file 6442 call ddb_hdr2%free() ! Free memory 6443 6444 end do 6445 6446 call ddb_hdr%close() 6447 6448 end if 6449 6450 ! ----------- 6451 ! Free memory 6452 ! ----------- 6453 call ddb_hdr%free() 6454 call ddb%free() 6455 6456 end subroutine merge_ddb
m_ddb/nlopt [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
nlopt
FUNCTION
Output of all quantities related to third-order derivatives of the energy. Compute the permutations of the three perturbations, then write out the whole matrix of third order derivatives in reduced coordinates. Finally, compute the non-linear optical susceptibility d and the first-order change in the dielectric susceptibility tensor induced by an atomic displacement.
INPUTS
blkflg(3,mpert,3,mpert,3,mpert)= ( 1 if the element of the 3dte has been calculated ; 0 otherwise ) d3(2,3,mpert,3,mpert,3,mpert)= matrix of the 3DTE gprimd(3,3)=dimensional primitive translations for reciprocal space(bohr^-1) mpert =maximum number of ipert natom= number of atoms rprimd(3,3)=dimensional primitive translations (bohr) ucvol=unit cell volume (bohr^3)
OUTPUT
carflg(3,mpert,3,mpert,3,mpert)=1 if the element of d3cart has been calculated, 0 otherwise d3cart(2,3,mpert,3,mpert,3,mpert)=matrix of third-order energy derivatives in cartesian coordinates
SOURCE
2263 subroutine nlopt(blkflg,carflg,d3,d3cart,gprimd,mpert,natom,rprimd,ucvol) 2264 2265 !Arguments ------------------------------- 2266 !scalars 2267 integer,intent(in) :: mpert,natom 2268 real(dp),intent(in) :: ucvol 2269 !arrays 2270 integer,intent(in) :: blkflg(3,mpert,3,mpert,3,mpert) 2271 integer,intent(out) :: carflg(3,mpert,3,mpert,3,mpert) 2272 real(dp),intent(in) :: d3(2,3,mpert,3,mpert,3,mpert),gprimd(3,3),rprimd(3,3) 2273 real(dp),intent(out) :: d3cart(2,3,mpert,3,mpert,3,mpert) 2274 2275 !Local variables ------------------------- 2276 !scalars 2277 integer :: i1dir,i1pert,i2dir,i2pert,i3dir,i3pert 2278 !arrays 2279 integer :: flg1(3),flg2(3) 2280 real(dp) :: vec1(3),vec2(3) 2281 2282 ! ******************************************************************* 2283 2284 !Compute the permutations of the perturbations 2285 2286 d3cart(:,:,:,:,:,:,:) = 0._dp 2287 2288 do i1pert = 1,mpert 2289 do i2pert = 1,mpert 2290 do i3pert = 1,mpert 2291 do i1dir=1,3 2292 do i2dir=1,3 2293 do i3dir=1,3 2294 2295 ! Check if all elements are available 2296 2297 if ((blkflg(i1dir,i1pert,i2dir,i2pert,i3dir,i3pert)/=0).and. & 2298 (blkflg(i1dir,i1pert,i3dir,i3pert,i2dir,i2pert)/=0).and. & 2299 (blkflg(i2dir,i2pert,i1dir,i1pert,i3dir,i3pert)/=0).and. & 2300 (blkflg(i2dir,i2pert,i3dir,i3pert,i1dir,i1pert)/=0).and. & 2301 (blkflg(i3dir,i3pert,i1dir,i1pert,i2dir,i2pert)/=0).and. & 2302 (blkflg(i3dir,i3pert,i2dir,i2pert,i1dir,i1pert)/=0)) then 2303 2304 d3cart(:,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) = & 2305 ( d3(:,i1dir,i1pert,i2dir,i2pert,i3dir,i3pert) + & 2306 d3(:,i1dir,i1pert,i3dir,i3pert,i2dir,i2pert) + & 2307 d3(:,i2dir,i2pert,i1dir,i1pert,i3dir,i3pert) + & 2308 d3(:,i2dir,i2pert,i3dir,i3pert,i1dir,i1pert) + & 2309 d3(:,i3dir,i3pert,i1dir,i1pert,i2dir,i2pert) + & 2310 d3(:,i3dir,i3pert,i2dir,i2pert,i1dir,i1pert))*sixth 2311 2312 end if 2313 end do 2314 end do 2315 end do 2316 end do 2317 end do 2318 end do 2319 2320 !Transform to cartesian coordinates 2321 carflg(:,:,:,:,:,:) = 0 2322 2323 do i1pert = 1, mpert 2324 do i2pert = 1, mpert 2325 do i3pert = 1, mpert 2326 2327 do i2dir = 1, 3 2328 do i3dir = 1, 3 2329 2330 vec1(:) = d3cart(1,:,i1pert,i2dir,i2pert,i3dir,i3pert) 2331 flg1(:) = blkflg(:,i1pert,i2dir,i2pert,i3dir,i3pert) 2332 call cart39(flg1,flg2,gprimd,i1pert,natom,rprimd,vec1,vec2) 2333 d3cart(1,:,i1pert,i2dir,i2pert,i3dir,i3pert) = vec2(:) 2334 carflg(:,i1pert,i2dir,i2pert,i3dir,i3pert) = flg2(:) 2335 2336 end do 2337 end do 2338 2339 do i1dir = 1, 3 2340 do i3dir = 1, 3 2341 vec1(:) = d3cart(1,i1dir,i1pert,:,i2pert,i3dir,i3pert) 2342 flg1(:) = blkflg(i1dir,i1pert,:,i2pert,i3dir,i3pert) 2343 call cart39(flg1,flg2,gprimd,i2pert,natom,rprimd,vec1,vec2) 2344 d3cart(1,i1dir,i1pert,:,i2pert,i3dir,i3pert) = vec2(:) 2345 carflg(i1dir,i1pert,:,i2pert,i3dir,i3pert) = flg2(:) 2346 end do 2347 end do 2348 2349 do i1dir = 1, 3 2350 do i2dir = 1, 3 2351 vec1(:) = d3cart(1,i1dir,i1pert,i2dir,i2pert,:,i3pert) 2352 flg1(:) = blkflg(i1dir,i1pert,i2dir,i2pert,:,i3pert) 2353 call cart39(flg1,flg2,gprimd,i3pert,natom,rprimd,vec1,vec2) 2354 d3cart(1,i1dir,i1pert,i2dir,i2pert,:,i3pert) = vec2(:) 2355 carflg(i1dir,i1pert,i2dir,i2pert,:,i3pert) = flg2(:) 2356 end do 2357 end do 2358 2359 end do 2360 end do 2361 end do 2362 2363 ! Compute non linear-optical coefficients d_ijk (atomic units) 2364 i1pert = natom+2 2365 d3cart(:,:,i1pert,:,i1pert,:,i1pert) = -3._dp*d3cart(:,:,i1pert,:,i1pert,:,i1pert)/(ucvol*2._dp) 2366 2367 ! Compute first-order change in the electronic dielectric 2368 ! susceptibility (Bohr^-1) induced by an atomic displacement 2369 d3cart(1:2,1:3,1:natom,1:3,natom + 2,1:3,natom + 2) = -6._dp*d3cart(1:2,1:3,1:natom,1:3,natom + 2,1:3,natom + 2)/ucvol 2370 2371 end subroutine nlopt
m_ddb/rdddb9 [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
rdddb9
FUNCTION
This routine reads the derivative database entirely, for use in ppddb9, and performs some checks and symmetrisation At the end, the whole DDB is in central memory, contained in the array ddb%val(2,msize,ddb%nblok). The information on it is contained in the four arrays ddb%flg(msize,ddb%nblok) : blok flag for each element ddb%qpt(9,ddb%nblok) : blok wavevector (unnormalized) ddb%nrm(3,ddb%nblok) : blok wavevector normalization ddb%typ(ddb%nblok) : blok type
INPUTS
unddb = unit number for DDB io dimekb=dimension of ekb (for the time being, only for norm- conserving psps) iout=unit number for output of formatted data lmnmax=if useylm=1, max number of (l,m,n) comp. over all type of psps =if useylm=0, max number of (l,n) comp. over all type of psps mband=maximum number of bands mpert =maximum number of ipert msize=maximum size of data blocks msym =maximum number of symmetry elements in space group natom = number of atoms ntypat=number of atom types usepaw= 0 for non paw calculation; =1 for paw calculation [raw] = 1 -> do not perform any symetrization or transformation to cartesian coordinates. 0 (default) -> do perform these transformations.
OUTPUT
acell(3)=length scales of cell (bohr) amu(ntypat)=mass of the atoms (atomic mass unit) ddb: ddb blok datatype contents: ddb%flg(msize,nblok)= flag of existence for each element of the DDB ddb%nrm(3,nblok) : blok wavevector normalization ddb%qpt(9,nblok) : blok wavevector (unnormalized) ddb%typ(nblok) : blok type ddb%val(2,msize,nblok)= value of each complex element of the DDB ddb%nblok= number of bloks in the DDB gmet(3,3)=reciprocal space metric tensor in bohr**-2 gprim(3,3)=dimensionless reciprocal space primitive translations indsym(4,msym,natom)=indirect indexing array for symmetries natom=number of atoms in cell nsym=number of space group symmetries rmet(3,3)=metric tensor in real space (bohr^2) rprim(3,3)= primitive translation vectors symrec(3,3,nsym)=3x3 matrices of the group symmetries (reciprocal space) symrel(3,3,nsym)=3x3 matrices of the group symmetries (real space) symafm(nsym)=Anti-ferromagnetic symmetries. tnons(3,nsym)=fractional nonsymmorphic translations typat(natom)=type integer for each atom in cell ucvol=unit cell volume in bohr**3 xcart(3,natom)=atomic cartesian coordinates xred(3,natom)=fractional dimensionless atomic coordinates zion(ntypat)=charge on each type of atom (real number) znucl(ntypat)=Nuclear charge for each type of pseudopotential
SOURCE
2048 subroutine rdddb9(ddb,ddb_hdr,unddb,& 2049 acell,amu,gmet,gprim,indsym,& 2050 mband,mpert,msize,msym,natom,nkpt,nsym,ntypat,& 2051 rmet,rprim,symrec,symrel,symafm,tnons,typat,ucvol,& 2052 xcart,xred,zion,znucl,raw) 2053 2054 !Arguments ------------------------------- 2055 ! NOTE: these are used for dimensioning and then re-assigned in ioddb8. 2056 ! This is almost definitely bad practice. In particular 2057 ! it should be indsym(4,msym,natom), 2058 ! and 2059 ! the allocation allocate(kpt(3,nkpt)) is strange 2060 !scalars 2061 integer,intent(in) :: unddb,mband,mpert,msize,msym 2062 integer,intent(inout) :: natom,nkpt,nsym,ntypat 2063 real(dp),intent(out) :: ucvol 2064 type(ddb_type),intent(inout) :: ddb 2065 type(ddb_hdr_type),intent(inout) :: ddb_hdr 2066 integer,optional,intent(in) :: raw 2067 !arrays 2068 integer,intent(inout) :: indsym(4,msym,natom) 2069 integer,intent(out) :: symrec(3,3,msym),symrel(3,3,msym),symafm(msym) 2070 integer,intent(out) :: typat(natom) 2071 real(dp),intent(out) :: acell(3),amu(ntypat) 2072 real(dp),intent(out) :: gmet(3,3),gprim(3,3),rmet(3,3) 2073 real(dp),intent(out) :: rprim(3,3),tnons(3,msym),xcart(3,natom),xred(3,natom) 2074 real(dp),intent(out) :: zion(ntypat),znucl(ntypat) 2075 2076 !Local variables ------------------------- 2077 !mtyplo=maximum number of type, locally 2078 !scalars 2079 integer,parameter :: msppol=2,mtyplo=6 2080 integer :: raw_ 2081 integer :: iblok,isym 2082 real(dp),parameter :: tolsym8=tol8 2083 !arrays 2084 real(dp) :: gprimd(3,3),rprimd(3,3) 2085 2086 ! ********************************************************************* 2087 2088 DBG_ENTER("COLL") 2089 2090 if (present(raw)) then 2091 raw_ = raw 2092 else 2093 raw_ = 0 2094 end if 2095 2096 ! FIXME 2097 ! GA: Most of this stuff could be moved up to the calling routine 2098 2099 nsym = ddb_hdr%nsym 2100 acell = ddb_hdr%acell 2101 rprim = ddb_hdr%rprim 2102 2103 amu(:) = ddb_hdr%amu(1:ntypat) 2104 typat(:) = ddb_hdr%typat(1:natom) 2105 zion(:) = ddb_hdr%zion(1:ntypat) 2106 znucl(:) = ddb_hdr%znucl(1:ntypat) 2107 2108 symafm(:) = ddb_hdr%symafm(:) 2109 symrel(:,:,:) = ddb_hdr%symrel(:,:,:) 2110 tnons(:,:) = ddb_hdr%tnons(:,:) 2111 2112 xred(:,:) = ddb_hdr%xred(:,:) 2113 2114 !call ddb_hdr%free() 2115 2116 ! Compute different matrices in real and reciprocal space, also 2117 ! checks whether ucvol is positive. 2118 call mkrdim(acell,rprim,rprimd) 2119 2120 ! call metric without printing to output 2121 call metric(gmet,gprimd,-1,rmet,rprimd,ucvol) 2122 2123 ! Obtain reciprocal space primitive transl g from inverse trans of r 2124 ! (Unlike in abinit, gprim is used throughout ifc; should be changed, later) 2125 call matr3inv(rprim,gprim) 2126 2127 ! Generate atom positions in cartesian coordinates 2128 call xred2xcart(natom,rprimd,xcart,xred) 2129 2130 ! Transposed inversion of the symmetry matrices, for use in the reciprocal space 2131 do isym=1,nsym 2132 call mati3inv(symrel(:,:,isym),symrec(:,:,isym)) 2133 end do 2134 2135 ! SYMATM generates for all the atoms and all the symmetries, the atom 2136 ! on which the referenced one is sent and also the translation bringing 2137 ! back this atom to the referenced unit cell 2138 ! GA: symatm was already called in crystal_init, no need to do it again. 2139 call symatm(indsym,natom,nsym,symrec,tnons,tolsym8,typat,xred) 2140 2141 !write(msg, '(3a,i0,a)' )ch10,ch10,' rdddb9: read ',ddb%nblok,' blocks from the input DDB ' 2142 !call wrtout(std_out,msg) 2143 2144 ! Read the blocks from the input database, and close it. 2145 do iblok=1,ddb%nblok 2146 2147 call ddb%read_block_txt(iblok,mband,mpert,msize,nkpt,unddb) 2148 2149 if (raw_ == 0) then 2150 call ddb%symmetrize_and_transform(ddb_hdr%crystal,iblok) 2151 end if 2152 2153 end do ! iblok 2154 2155 DBG_EXIT("COLL") 2156 2157 end subroutine rdddb9
m_ddb/symdm9 [ Functions ]
[ Top ] [ m_ddb ] [ Functions ]
NAME
symdm9
FUNCTION
Use the set of special k points calculated by the Monkhorst & Pack Technique. Check if all the information for the k points are present in the DDB to determine their dynamical matrices. Generate the dynamical matrices of the set of k points which samples homogeneously the entire Brillouin zone.
INPUTS
%flg(nsize,nblok)= flag of existence for each element of the DDB %nrm(1,nblok)=norm of qpt providing normalization %qpt(1<ii<9,nblok)=q vector of a phonon mode (ii=1,2,3) %typ(nblok)=1 or 2 depending on non-stationary or stationary block 3 for third order derivatives %val(2,3*mpert*3*mpert,nblok)= all the dynamical matrices gprimd(3,3)=dimensionlal primitive translations in reciprocal space indsym = mapping of atoms under symops mpert =maximum number of ipert natom=number of atoms in unit cell %nblok=number of blocks in the DDB nqpt=number of special q points nsym=number of space group symmetries rfmeth = 1 or -1 if non-stationary block 2 or -2 if stationary block 3 or -3 if third order derivatives 85 if molecular Berry curvature positive if symmetries are used to set elements to zero whenever possible, negative to prevent this to happen. rprimd(3,3)=dimensional primitive translations in real space spqpt(3,nqpt)=set of special q points generated by the Monkhorst & Pack Method symrec(3,3,nsym)=3x3 matrices of the group symmetries (reciprocal space) symrel(3,3,nsym)=3x3 matrices of the group symmetries (real space) comm=MPI communicator.
OUTPUT
dynmat(2,3,natom,3,natom,nqpt)=dynamical matrices relative to the q points of the B.Z. sampling [qmissing]=Allocatable array with the indices of the q-points in the BZ that could not be obtained by symmetry. If qmissing is present, the routine does not stop if the full BZ cannot be reconstructed. The caller is responsible for filling the missing entries.
TODO
* A full description of the inputs should be included
NOTES
Time-reversal symmetry is always assumed The time-reversal is correctly used for the MBC (Molecular Berry curvature): G(-k)=G^*(k)
SOURCE
6804 subroutine symdm9(ddb, dynmat, gprimd, indsym, mpert, natom, nqpt, nsym, rfmeth,& 6805 rprimd, spqpt, symrec, symrel, comm, qmissing) 6806 6807 !Arguments ------------------------------- 6808 !scalars 6809 type(ddb_type),intent(in) :: ddb 6810 integer,intent(in) :: mpert,natom,nqpt,nsym,rfmeth,comm 6811 !arrays 6812 integer,intent(in) :: indsym(4,nsym,natom),symrec(3,3,nsym),symrel(3,3,nsym) 6813 integer,allocatable,optional,intent(out) :: qmissing(:) 6814 real(dp),intent(in) :: gprimd(3,3),rprimd(3,3) 6815 real(dp),intent(in) :: spqpt(3,nqpt) 6816 real(dp),intent(out) :: dynmat(2,3,natom,3,natom,nqpt) 6817 6818 !Local variables ------------------------- 6819 !scalars 6820 integer :: ia,ib,iblok,idir1,idir2,ii,ipert1,ipert2,iqpt,isym,jj,kk,ll 6821 integer :: mu,nu,q1,q2,nqmiss,nprocs,my_rank,ierr,index 6822 real(dp),parameter :: tol=2.d-8 6823 real(dp) :: sign1, sign2 6824 !tolerance for equality of q points between those of the DDB and those of the sampling grid 6825 real(dp) :: arg1,arg2,im,re,sumi,sumr 6826 logical :: allow_qmiss 6827 character(len=500) :: msg 6828 !arrays 6829 integer,allocatable :: qtest(:,:) 6830 integer :: qmiss_(nqpt) 6831 real(dp) :: qq(3),qsym(6),ss(3,3) 6832 real(dp),allocatable :: ddd(:,:,:,:,:) 6833 6834 ! ********************************************************************* 6835 6836 nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm) 6837 6838 ! Initialize output (some q-points might not be reconstructed if qmissing is present) 6839 dynmat = zero 6840 allow_qmiss = (present(qmissing)) 6841 6842 ABI_MALLOC(ddd,(2,3,natom,3,natom)) 6843 ! Check if the blkqpt points and their symmetrics are sufficient 6844 ! in the DDB to retrieve all the q points of the B.Z. sampling 6845 6846 !Initialization of a test variable 6847 ! qtest(iqpt,1)=iblok 6848 ! qtest(iqpt,2)=isym 6849 ! qtest(iqpt,3)=time_reversal 6850 ABI_MALLOC(qtest,(nqpt,3)) 6851 do iqpt=1,nqpt 6852 qtest(iqpt,1)=0 6853 end do 6854 6855 !Q points coming from the DDB 6856 !write(std_out,*)' Nbr. of Blocks -> ',nblok 6857 ! TODO: This part scales badly with nblock/nqpt 6858 ! One could use listkk or rearrange the loop so that iqpt comes first and then MPI-parallelize. 6859 6860 do iblok=1,ddb%nblok 6861 6862 if (abs(ddb%typ(iblok)) == abs(rfmeth)) then 6863 qq(1)=ddb%qpt(1,iblok)/ddb%nrm(1,iblok) 6864 qq(2)=ddb%qpt(2,iblok)/ddb%nrm(1,iblok) 6865 qq(3)=ddb%qpt(3,iblok)/ddb%nrm(1,iblok) 6866 6867 ! Calculation of the symmetric points (including Time Reversal) 6868 do isym=1,nsym 6869 qsym(1)=qq(1)*symrec(1,1,isym)+qq(2)*symrec(1,2,isym)+qq(3)*symrec(1,3,isym) 6870 qsym(2)=qq(1)*symrec(2,1,isym)+qq(2)*symrec(2,2,isym)+qq(3)*symrec(2,3,isym) 6871 qsym(3)=qq(1)*symrec(3,1,isym)+qq(2)*symrec(3,2,isym)+qq(3)*symrec(3,3,isym) 6872 6873 ! Dont forget the Time Reversal symmetry 6874 qsym(4)=-qq(1)*symrec(1,1,isym)-qq(2)*symrec(1,2,isym)-qq(3)*symrec(1,3,isym) 6875 qsym(5)=-qq(1)*symrec(2,1,isym)-qq(2)*symrec(2,2,isym)-qq(3)*symrec(2,3,isym) 6876 qsym(6)=-qq(1)*symrec(3,1,isym)-qq(2)*symrec(3,2,isym)-qq(3)*symrec(3,3,isym) 6877 6878 ! Comparison between the q points and their symmetric points 6879 ! and the set of q points which samples the entire Brillouin zone 6880 do iqpt=1,nqpt 6881 6882 if (mod(abs(spqpt(1,iqpt)-qsym(1))+tol,1._dp)<2*tol)then 6883 if (mod(abs(spqpt(2,iqpt)-qsym(2))+tol,1._dp)<2*tol)then 6884 if (mod(abs(spqpt(3,iqpt)-qsym(3))+tol,1._dp)<2*tol)then 6885 6886 ! write(std_out,*)' q point from the DDB ! ' 6887 ! write(std_out,*)' block -> ',iblok 6888 ! write(std_out,*)' sym. -> ',isym 6889 ! write(std_out,*)' No Time Reversal ' 6890 ! write(std_out,*)'(',qsym(1),',',qsym(2),',',qsym(3),')' 6891 ! write(std_out,*)' ' 6892 qtest(iqpt,1)=iblok 6893 qtest(iqpt,2)=isym 6894 qtest(iqpt,3)=0 6895 end if 6896 end if 6897 end if 6898 6899 if (mod(abs(spqpt(1,iqpt)-qsym(4))+tol,1._dp)<2*tol)then 6900 if (mod(abs(spqpt(2,iqpt)-qsym(5))+tol,1._dp)<2*tol)then 6901 if (mod(abs(spqpt(3,iqpt)-qsym(6))+tol,1._dp)<2*tol)then 6902 6903 ! write(std_out,*)' q point from the DDB ! ' 6904 ! write(std_out,*)' block -> ',iblok 6905 ! write(std_out,*)' sym. -> ',isym 6906 ! write(std_out,*)' Time Reversal ' 6907 ! write(std_out,*)'(',qsym(4),',',qsym(5),',',qsym(6),')' 6908 ! write(std_out,*)' ' 6909 6910 qtest(iqpt,1)=iblok 6911 qtest(iqpt,2)=isym 6912 qtest(iqpt,3)=1 6913 end if 6914 end if 6915 end if 6916 6917 end do ! iqpt 6918 end do ! isym 6919 6920 end if 6921 end do ! iblok 6922 6923 ! Check if all the information relatives to the q points sampling are found in the DDB; 6924 ! if not => stop message 6925 nqmiss = 0 6926 do iqpt=1,nqpt 6927 if (qtest(iqpt,1)==0) then 6928 nqmiss = nqmiss + 1 6929 qmiss_(nqmiss) = iqpt 6930 write(msg, '(3a)' )& 6931 ' symdm9: the bloks found in the DDB are characterized',ch10,& 6932 ' by the following wavevectors :' 6933 call wrtout(std_out,msg) 6934 do iblok=1,ddb%nblok 6935 write(msg, '(a,4d20.12)')' ',ddb%qpt(1,iblok),ddb%qpt(2,iblok),ddb%qpt(3,iblok),ddb%nrm(1,iblok) 6936 call wrtout(std_out,msg) 6937 end do 6938 write(msg, '(a,a,a,i0,a,a,a,3es16.6,a,a,a,a)' )& 6939 'Information is missing in the DDB.',ch10,& 6940 'The dynamical matrix number ',iqpt,' cannot be built,',ch10,& 6941 'since no block with qpt:',spqpt(1:3,iqpt),ch10,& 6942 'has been found.',ch10,& 6943 'Action: add the required block in the DDB, or modify the q-mesh your input file.' 6944 if (.not.allow_qmiss) then 6945 ABI_ERROR(msg) 6946 else 6947 !continue 6948 ABI_COMMENT(msg) 6949 end if 6950 end if 6951 end do 6952 6953 ! Will return a list with the index of the q-points that could not be symmetrized. 6954 if (allow_qmiss) then 6955 ABI_MALLOC(qmissing, (nqmiss)) 6956 if (nqmiss > 0) qmissing = qmiss_(1:nqmiss) 6957 end if 6958 6959 ! Generation of the dynamical matrices relative to the q points 6960 ! of the set which samples the entire Brillouin zone 6961 do iqpt=1,nqpt 6962 if (mod(iqpt, nprocs) /= my_rank) cycle ! mpi-parallelism 6963 6964 q1=qtest(iqpt,1) ! iblok 6965 q2=qtest(iqpt,2) ! isym 6966 ! Skip this q-point if don't have enough info and allow_qmiss 6967 if (allow_qmiss .and. q1==0) cycle 6968 6969 ! Check if the symmetry accompagnied with time reversal : q <- -q 6970 do ii=1,3 6971 qq(ii)=ddb%qpt(ii,q1)/ddb%nrm(1,q1) 6972 end do 6973 if (qtest(iqpt,3)/=0) qq(:) = -qq(:) 6974 ! 6975 do ii=1,3 6976 do jj=1,3 6977 ss(ii,jj)=zero 6978 do kk=1,3 6979 do ll=1,3 6980 ss(ii,jj) = ss(ii,jj) + rprimd(ii,kk) * symrel(kk,ll,q2) * gprimd(jj,ll) 6981 end do 6982 end do 6983 end do 6984 end do 6985 6986 ! Check whether all the information is contained in the DDB 6987 do ipert2=1,natom 6988 do idir2=1,3 6989 do ipert1=1,natom 6990 do idir1=1,3 6991 index = idir1+ 3*((ipert1-1)+ddb%mpert*((idir2-1)+3*(ipert2-1))) 6992 !if(ddb%flg(idir1,ipert1,idir2,ipert2,q1)/=1)then 6993 if(ddb%flg(index,q1)/=1)then 6994 write(msg, '(a,a,a,i0,a,a,a,4(i0,1x),a,a,a,a)' )& 6995 'Elements are missing in the DDB.',ch10,& 6996 'In block iq1: ',q1,' the following element is missing: ',ch10,& 6997 '(idir1, ipert1, idir2, ipert2): ',idir1,ipert1,idir2,ipert2,ch10,& 6998 'Action: add the required information in the DDB with mrgddb,',ch10,& 6999 'and/or check that all irreducible perturbations have been computed.' 7000 ABI_ERROR(msg) 7001 end if 7002 end do 7003 end do 7004 end do 7005 end do 7006 7007 ! Read the dynamical matrices in the DDB 7008 do ipert2=1,natom 7009 do idir2=1,3 7010 do ipert1=1,natom 7011 do idir1=1,3 7012 ddd(:,idir1,ipert1,idir2,ipert2)=ddb%val(:,idir1+3*(ipert1-1+mpert*(idir2-1+3*(ipert2-1))),q1) 7013 end do 7014 end do 7015 end do 7016 end do 7017 7018 ! determine sign of complex conjugation 7019 ! If there is Time Reversal : D.M. <- Complex Conjugate D.M. 7020 ! MBC <- Complex Conjugate MBC 7021 if (qtest(iqpt,3)==0) then 7022 sign1 = one 7023 sign2 = one 7024 else ! if timrev -> complex conjugate 7025 sign1 = one 7026 sign2 = -one 7027 end if 7028 7029 ! Calculation of the dynamical matrix of a symmetrical q point 7030 do ia=1,natom 7031 do ib=1,natom 7032 ! write(std_out,*)'atom-> ',ia,indsym(4,q2,ia); write(std_out,*)'atom-> ',ib,indsym(4,q2,ib) 7033 arg1=two_pi*(qq(1)*indsym(1,q2,ia)+qq(2)*indsym(2,q2,ia)+qq(3)*indsym(3,q2,ia)) 7034 arg2=two_pi*(qq(1)*indsym(1,q2,ib)+qq(2)*indsym(2,q2,ib)+qq(3)*indsym(3,q2,ib)) 7035 re=cos(arg1)*cos(arg2)+sin(arg1)*sin(arg2) 7036 im=cos(arg2)*sin(arg1)-cos(arg1)*sin(arg2) 7037 do mu=1,3 7038 do nu=1,3 7039 sumr=zero 7040 sumi=zero 7041 do ii=1,3 7042 do jj=1,3 7043 sumr=sumr+ss(mu,ii)*ss(nu,jj)*ddd(1,ii,indsym(4,q2,ia),jj,indsym(4,q2,ib)) 7044 sumi=sumi+ss(mu,ii)*ss(nu,jj)*ddd(2,ii,indsym(4,q2,ia),jj,indsym(4,q2,ib)) 7045 end do 7046 end do 7047 7048 ! Dynmat -> Dynamical Matrix for the q point of the sampling 7049 ! write(std_out,*)' Sumr -> ',mu,nu,sumr; write(std_out,*)' Sumi -> ',mu,nu,sumi 7050 dynmat(1,mu,ia,nu,ib,iqpt) = sign1*re*sumr - sign2*im*sumi 7051 dynmat(2,mu,ia,nu,ib,iqpt) = sign2*re*sumi + sign1*im*sumr 7052 end do ! coordinates 7053 end do 7054 7055 end do ! ia atoms 7056 end do ! ib atoms 7057 end do ! q points of the sampling 7058 7059 ABI_FREE(ddd) 7060 ABI_FREE(qtest) 7061 7062 7063 call xmpi_sum(dynmat, comm, ierr) 7064 7065 end subroutine symdm9