TABLE OF CONTENTS
- ABINIT/m_bse_io
- m_bse_io/ccs_of_glob
- m_bse_io/exc_amplitude
- m_bse_io/exc_fullh_from_blocks
- m_bse_io/exc_read_bshdr
- m_bse_io/exc_read_eigen
- m_bse_io/exc_read_rblock_fio
- m_bse_io/exc_read_rcblock
- m_bse_io/exc_skip_bshdr
- m_bse_io/exc_skip_bshdr_mpio
- m_bse_io/exc_write_bshdr
- m_bse_io/exc_write_optme
- m_bse_io/offset_in_file
- m_bse_io/rrs_of_glob
- m_hexc/exc_ham_ncwrite
ABINIT/m_bse_io [ Modules ]
NAME
m_bse_io
FUNCTION
This module provides routines to read the Bethe-Salpeter Hamiltonian from file
COPYRIGHT
Copyright (C) 2008-2024 ABINIT group (MG) 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
16 #if defined HAVE_CONFIG_H 17 #include "config.h" 18 #endif 19 20 #include "abi_common.h" 21 22 MODULE m_bse_io 23 24 use defs_basis 25 use m_xmpi 26 use m_errors 27 use m_abicore 28 #if defined HAVE_MPI2 29 use mpi 30 #endif 31 use netcdf 32 use m_nctk 33 use, intrinsic :: iso_c_binding 34 use m_hdr 35 36 use m_time, only : cwtime 37 use m_fstrings, only : toupper 38 use m_io_tools, only : open_file 39 use m_numeric_tools, only : arth 40 use m_special_funcs, only : gaussian 41 use m_bs_defs, only : excparam 42 use m_bz_mesh, only : kmesh_t 43 44 implicit none 45 46 #if defined HAVE_MPI1 47 include 'mpif.h' 48 #endif 49 50 private 51 52 public :: exc_read_rblock_fio ! Reads the entire resonant sub-block from file using Fortran IO. 53 public :: exc_read_rcblock ! Reads a distributed sub-block of the excitonic Hamiltonian from file. 54 public :: exc_fullh_from_blocks ! Initialize the specified sub-blocks of the *full* matrix (reso+anti-reso) from file. 55 public :: rrs_of_glob ! [+1,-1,0] if (row_glob,col_glob) belongs to the [ resonant, anti-resonant, (anti)coupling block ] 56 public :: ccs_of_glob ! [+1,-1,0] if (row_glob,col_glob) belongs to the [ coupling, anti-coupling, (anti)resonant block ] 57 public :: offset_in_file ! Function used to describe the way the Hamiltonian is stored on disk. 58 public :: exc_write_bshdr ! Writes the Header of the (BSR|BSC) files storing the excitonic Hamiltonian. 59 public :: exc_read_bshdr ! Reads the Header of the (BSR|BSC) files. 60 public :: exc_skip_bshdr ! Skip the Header of the (BSR|BSC) files. Fortran version. 61 public :: exc_skip_bshdr_mpio ! Skip the Header of the (BSR|BSC) files. MPI-IO version. 62 public :: exc_read_eigen ! Read selected energies and eigenvectors from the BSEIG file. 63 public :: exc_amplitude ! Calculate the amplitude function F(w) = \sum_t |<t|exc_vec>|^2 \delta(ww- ene_t) where t is the eh transition. 64 public :: exc_write_optme ! Writes the OME file storing the optical matrix elements 65 public :: exc_ham_ncwrite ! Writes the hamiltonian in NETCDF format
m_bse_io/ccs_of_glob [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
FUNCTION
[+1,-1,0] if (row_glob,col_glob) belongs to the [ coupling, anti-coupling, (anti)resonant block ]
INPUTS
OUTPUT
SOURCE
1015 pure function ccs_of_glob(row_glob,col_glob,size_glob) 1016 1017 !Arguments ------------------------------------ 1018 integer :: ccs_of_glob 1019 integer,intent(in) :: row_glob,col_glob 1020 integer,intent(in) :: size_glob(2) 1021 1022 !Local variables ------------------------------ 1023 !scalars 1024 integer :: nreh1,nreh2 1025 1026 ! ************************************************************************* 1027 1028 nreh1=size_glob(1)/2 ! Matrix is square and nreh1==nreh2 but oh well. 1029 nreh2=size_glob(2)/2 1030 1031 if (row_glob<=nreh1 .and. col_glob >nreh2) then ! Coupling. 1032 ccs_of_glob = +1 1033 else if (row_glob >nreh1 .and. col_glob<=nreh2) then ! anti-Coupling 1034 ccs_of_glob = -1 1035 else 1036 ccs_of_glob = 0 1037 end if 1038 1039 end function ccs_of_glob
m_bse_io/exc_amplitude [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
exc_amplitude
FUNCTION
Calculate the amplitude function of the excitonic eigenstate |exc_vec\> F(w) = \sum_t |<t|exc_vec>|^2 \delta(ww- ene_t) where the sum over t is done of the full set of transitions used to construct the BS Hamiltoniam.
INPUTS
Bsp<excparam>=Structure storing the parameters of the run. eig_fname=The name of the file storing the excitonic eigenvectors. nvec=Number of excitonic states to analyze. vec_idx(nvec)=List with the indices of the excitonic states sorted in ascending order. out_fname=The name of the file where the results are written.
OUTPUT
Only writing.
SOURCE
1234 subroutine exc_amplitude(Bsp,eig_fname,nvec,vec_idx,out_fname) 1235 1236 !Arguments ------------------------------------ 1237 !scalars 1238 integer,intent(in) :: nvec 1239 character(len=*),intent(in) :: eig_fname,out_fname 1240 type(excparam),intent(in) :: BSp 1241 ! arrays 1242 integer,intent(in) :: vec_idx(nvec) 1243 1244 !Local variables ------------------------------ 1245 !scalars 1246 integer :: vec,art_idx,ierr 1247 integer :: spin,iw,it,nw,pos_w,neg_w,out_unt,rt_idx,hsize 1248 real(dp) :: ene_rt,ampl_eh,ampl_he,xx,stdev,w_max,w_min,step 1249 character(len=500) :: msg 1250 !arrays 1251 real(dp),allocatable :: wmesh(:),amplitude(:),ene_list(:) 1252 complex(dpc),allocatable :: vec_list(:,:) 1253 1254 ! ************************************************************************* 1255 1256 ! Setup of the frequency mesh for F(w). 1257 w_min=greatest_real; w_max=smallest_real 1258 do spin=1,BSp%nsppol 1259 do it=1,BSp%nreh(spin) 1260 ene_rt = Bsp%Trans(it,spin)%en 1261 w_min = MIN(w_min,ene_rt) 1262 w_max = MAX(w_max,ene_rt) 1263 end do 1264 end do 1265 1266 step = Bsp%domega 1267 if (Bsp%use_coupling==0) then 1268 nw = (w_max - w_min)/step + 1 1269 ABI_MALLOC(wmesh,(nw)) 1270 wmesh = arth(w_min,step,nw) 1271 else 1272 ! Both positive and negative frequencies are needed. 1273 pos_w = (w_max - w_min)/step + 1 1274 neg_w = pos_w; if (ABS(w_min) < tol6) neg_w=neg_w-1 ! zero should not included twice. 1275 nw = neg_w + pos_w 1276 ABI_MALLOC(wmesh,(nw)) 1277 wmesh(1:neg_w) = arth(-w_max,step,neg_w) 1278 wmesh(neg_w+1:) = arth( w_min,step,pos_w) 1279 end if 1280 ! 1281 ! Read selected eigenvectors. 1282 hsize = SUM(Bsp%nreh); if (Bsp%use_coupling>0) hsize=2*hsize 1283 1284 ABI_MALLOC(ene_list,(nvec)) 1285 ABI_MALLOC_OR_DIE(vec_list,(hsize,nvec), ierr) 1286 1287 call exc_read_eigen(eig_fname,hsize,nvec,vec_idx,vec_list,ene_list,Bsp=Bsp) 1288 1289 ABI_FREE(ene_list) 1290 1291 if (open_file(out_fname,msg,newunit=out_unt,form="formatted",action="write") /= 0) then 1292 ABI_ERROR(msg) 1293 end if 1294 1295 write(out_unt,*)"# Amplitude functions F(w) = \sum_t |<t|exc_vec>|^2 \delta(ww- ene_t), w is given in eV. " 1296 write(out_unt,*)"# Number of excitonic eigenvectors analyzed: ",nvec 1297 1298 ABI_MALLOC(amplitude,(nw)) 1299 stdev = BSp%broad ! Broadening for the gaussian. 1300 1301 do vec=1,nvec 1302 ! 1303 ! amplitude(ww) = \sum_t |<t|exc_vec>|^2 \delta(ww- ene_t) 1304 amplitude = zero 1305 do spin=1,BSp%nsppol 1306 do it=1,BSp%nreh(spin) 1307 ene_rt = Bsp%Trans(it,spin)%en 1308 rt_idx = it + (spin-1)*Bsp%nreh(1) 1309 ampl_eh = (ABS(vec_list(rt_idx,vec)))**2 1310 if (Bsp%use_coupling>0) then ! Need the index and the amplitude of the anti-resonant component. 1311 art_idx = it + (spin-1)*Bsp%nreh(1) + SUM(Bsp%nreh) 1312 ampl_he = (ABS(vec_list(art_idx,vec)))**2 1313 end if 1314 ! 1315 do iw=1,nw ! Accumulate 1316 xx = wmesh(iw) - ene_rt 1317 amplitude(iw) = amplitude(iw) + ampl_eh * gaussian(xx, stdev) 1318 if (Bsp%use_coupling>0) then 1319 xx = wmesh(iw) + ene_rt 1320 amplitude(iw) = amplitude(iw) + ampl_he * gaussian(xx, stdev) 1321 end if 1322 end do 1323 ! 1324 end do 1325 end do 1326 ! 1327 ! Write results 1328 write(out_unt,*)"# Amplitude function F(w) for exc_vector index ",vec_idx(vec) 1329 do iw=1,nw 1330 write(out_unt,*)wmesh(iw)*Ha_eV,amplitude(iw) 1331 end do 1332 write(out_unt,*)"#" 1333 end do 1334 1335 close(out_unt) 1336 1337 ABI_FREE(amplitude) 1338 ABI_FREE(wmesh) 1339 ABI_FREE(vec_list) 1340 1341 end subroutine exc_amplitude
m_bse_io/exc_fullh_from_blocks [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
exc_fullh_from_blocks
FUNCTION
Construct the matrix F H
INPUTS
funt nsppol block_type "Resonant" "Coupling" row_sign -1 to read ( R C ) (-C* -R*) +1 to read ( R C ) ( C* R*) diago_is_real=Used when block_type=resonat to specify wheter the diagonal matrix elements are real or complex (when QP linewidth are included) nreh(nsppol) exc_size=Size of the full excitonic Hamiltonian.
SIDE EFFECTS
exc_ham(exc_size,exc_size)
NOTES
SOURCE
725 subroutine exc_fullh_from_blocks(funt,block_type,nsppol,row_sign,diago_is_real,nreh,exc_size,exc_ham) 726 727 !Arguments ------------------------------------ 728 !scalars 729 integer,intent(in) :: funt,exc_size,nsppol,row_sign 730 logical,intent(in) :: diago_is_real 731 character(len=*),intent(in) :: block_type 732 !arrays 733 integer,intent(in) :: nreh(nsppol) 734 complex(dpc),intent(inout) :: exc_ham(exc_size,exc_size) 735 736 !Local variables------------------------------- 737 !scalars 738 integer :: it,itp,szbuf,neh,pad_c1,pad_r1,spin_dim,spad_r,spad_c 739 integer :: block,spad,row1,col1,row2,col2,spin_stride,ierr 740 complex(dpc) :: cttp 741 character(len=500) :: errmsg 742 !arrays 743 complex(dpc),allocatable :: cbuff_dpc(:) 744 745 ! ********************************************************************* 746 747 szbuf=exc_size ! FIXME oversized! 748 neh = nreh(1) 749 750 if (nsppol==2) then 751 ABI_WARNING("nsppol==2 is very experimental") 752 end if 753 if (ANY(nreh(1)/=nreh)) then 754 ABI_ERROR(" different nreh are not supported") 755 end if 756 757 ABI_MALLOC_OR_DIE(cbuff_dpc,(exc_size), ierr) 758 ! 759 ! The two cases nsppol==1,2 can be merged but we keep them 760 ! separated to keep to code readable. 761 762 SELECT CASE (toupper(block_type)) 763 CASE ("RESONANT") 764 765 if (nsppol==1) then 766 ! 767 ! Construct resonant block from the upper triangle stored on file. 768 neh = nreh(1) 769 do itp=1,neh 770 read(funt, err=10, iomsg=errmsg) cbuff_dpc(1:itp) 771 do it=1,itp-1 ! The diagonal is treated below. 772 cttp = cbuff_dpc(it) 773 exc_ham(it ,itp) = cttp ! R 774 exc_ham(itp ,it ) = CONJG(cttp) ! row_sign R* 775 exc_ham(neh+it ,neh+itp) = row_sign*CONJG(cttp) 776 exc_ham(neh+itp,neh+it ) = row_sign*cttp 777 end do 778 if (diago_is_real) then 779 exc_ham(itp ,itp) = DBLE(cbuff_dpc(itp)) 780 exc_ham(neh+itp,neh+itp) = row_sign*DBLE(cbuff_dpc(itp)) 781 else 782 exc_ham(itp,itp) = cbuff_dpc(itp) 783 exc_ham(neh+itp,neh+itp) = row_sign*(CONJG(cbuff_dpc(itp))) 784 end if 785 end do 786 ! 787 ! 788 else 789 ! FIXME this part wont work if we have a different number of e-h pairs 790 ABI_CHECK(ALL(nreh==nreh(1)),"Different number of transitions") 791 ! The file contains 792 ! A) The up-up and the down-down block in packed form 793 ! (only the upper triangle is stored since these blocks are Hermitian) 794 ! B) The entire up-down exchange block (no symmetry here) 795 ! 796 ! The resonant block is given by: 797 ! | (v'c' up) | (v'c' dwn) | 798 ! ------------------------------ where v_{-+} = v_{+-}^H when the momentum of the photon is neglected. 799 ! | [T-W+v]++ | v+- | (vc up) Note that v_{+-} is not Hermitian due to the presence of different spins. 800 ! R = ------------------------------ Actually it reduces to a Hermitian matrix when the system is not spin polarized. 801 ! | v-+ | [T-W+v]-- | (vc dwn) [T-W+v] is Hermitian provided the the QP energies are purely real. 802 ! ------------------------------ 803 ! 804 ! *) Fill the diagonal blocks. 805 ! only the upper triangle is stored on file. 806 ! row1,col1 refer to the resonant block. 807 ! row2,col2 refer to the anti-resonant block. 808 do block=1,2 809 if (block==1) then 810 spad=0 811 spin_stride=SUM(nreh) 812 end if 813 if (block==2) then 814 spad=nreh(1) 815 spin_stride=2*nreh(1) + nreh(2) 816 end if 817 do itp=1,nreh(block) 818 read(funt, err=10, iomsg=errmsg) cbuff_dpc(1:itp) 819 col1 = itp+spad 820 col2 = itp+spin_stride 821 do it=1,itp-1 822 cttp = cbuff_dpc(it) 823 row1 = it + spad 824 row2 = it + spin_stride 825 exc_ham(row1,col1) = cttp ! [T-W+v] 826 exc_ham(col1,row1) = CONJG(cttp) 827 exc_ham(row2,col2) = row_sign*CONJG(cttp) ! row_sign [T-W+v]* 828 exc_ham(col2,row2) = row_sign*cttp 829 end do 830 if (diago_is_real) then 831 exc_ham(col1,col1) = DBLE(cbuff_dpc(itp)) 832 exc_ham(col2,col2) = row_sign*DBLE(cbuff_dpc(itp)) 833 else 834 exc_ham(col1,col1) = cbuff_dpc(itp) 835 exc_ham(col2,col2) = row_sign*CONJG(cbuff_dpc(itp)) 836 end if 837 end do 838 end do 839 ! 840 ! Read v+- and reconstruct resonant and anti-resonat blocks. 841 ! TODO recheck this 842 pad_r1=SUM(nreh) 843 pad_c1=2*nreh(1) + nreh(2) 844 845 spin_dim=nreh(1) 846 do itp=1,spin_dim 847 read(funt, err=10, iomsg=errmsg) cbuff_dpc(1:spin_dim) 848 exc_ham(1:spin_dim,nreh(1)+itp) = cbuff_dpc(1:spin_dim) ! upper reso 849 exc_ham(1+pad_r1:pad_r1+spin_dim,pad_c1+itp) = row_sign*CONJG(cbuff_dpc(1:spin_dim)) ! upper anti-reso 850 col1 = itp+nreh(1) 851 col2 = itp+(2*nreh(1) + nreh(2)) 852 do it=1,spin_dim 853 cttp = cbuff_dpc(it) 854 row1 = it 855 exc_ham(col1,row1) = CONJG(cttp) ! lower reso. 856 row2 = it + SUM(nreh) 857 exc_ham(col2,row2) = row_sign*cttp ! lower anti-reso. 858 end do 859 end do 860 end if 861 862 CASE ("COUPLING") 863 ! 864 if (nsppol==1) then 865 ! 866 do itp=1,neh 867 read(funt, err=10, iomsg=errmsg) cbuff_dpc(1:itp) 868 do it=1,itp 869 cttp = cbuff_dpc(it) 870 exc_ham(it ,neh+itp) = cttp 871 exc_ham(itp ,neh+it ) = cttp 872 exc_ham(neh+it ,itp ) = row_sign*CONJG(cttp) 873 exc_ham(neh+itp,it ) = row_sign*CONJG(cttp) 874 end do 875 end do 876 ! 877 else 878 ! The coupling block is given by: 879 ! | (c'v' up) | (c'v dwn) | 880 ! ----------------------------------- where v_{-+} = v_{+-}^t when the momentum of the photon is neglected. 881 ! | [-W+v]++ | v+- | (vc up) The entire matrix v_{+-} is stored on file. 882 ! C = ----------------------------------- 883 ! | v-+ | [-W+v]-- | (vc dwn) 884 ! ----------------------------------- 885 ! 886 ! *) Fill blocks that are diagonal in spin coordinates. 887 ! row1,col1 refer to the resonat block. 888 ! row2,col2 refer to the anti-resonant block. 889 do block=1,2 890 if (block==1) then 891 spad_r=0 892 spad_c=SUM(nreh) 893 end if 894 if (block==2) then 895 spad_r=nreh(1) 896 spad_c=2*nreh(1)+nreh(2) 897 end if 898 do itp=1,nreh(block) 899 read(funt, err=10, iomsg=errmsg) cbuff_dpc(1:itp) 900 col1 = itp+spad_c 901 row2 = itp+spad_r 902 do it=1,itp-1 903 cttp = cbuff_dpc(it) 904 row1 = it + spad_r 905 col2 = it + spad_c 906 exc_ham(row1,col1) = cttp ! upper coupling 907 exc_ham(row2,col2) = cttp ! lower coupling (symmetric) 908 exc_ham(col1,row1) = row_sign*CONJG(cttp) ! lower anti-coupling 909 exc_ham(col2,row2) = row_sign*CONJG(cttp) ! upper anti-couling 910 end do 911 ! TODO recheck this 912 row1 = itp+spad_r 913 exc_ham(row1,col1) = cbuff_dpc(itp) ! Diagonals of the block. 914 col2 = itp+spad_c 915 exc_ham(col2,row2) = row_sign*CONJG(cbuff_dpc(itp)) 916 end do 917 end do 918 ! 919 ! Read Full v+- and reconstruct resonant and anti-resonat blocks. 920 ! TODO recheck this 921 spad=2*nreh(1) + nreh(2) 922 pad_r1=SUM(nreh) 923 pad_c1=2*nreh(1) + nreh(2) 924 925 spin_dim=nreh(1) 926 do itp=1,spin_dim 927 read(funt, err=10, iomsg=errmsg) cbuff_dpc(1:spin_dim) 928 exc_ham(1:spin_dim,spad+itp) = cbuff_dpc(1:spin_dim) ! upper block reso 929 exc_ham(1+pad_r1:pad_r1+spin_dim,nreh(1)+itp) = row_sign*CONJG(cbuff_dpc(1:spin_dim)) ! upper block anti-reso 930 col1 = itp+spad 931 row2 = itp+nreh(1) 932 do it=1,spin_dim 933 cttp = cbuff_dpc(it) 934 row1 = it 935 exc_ham(col1,row1) = row_sign*CONJG(cttp) ! lower anti-reso. 936 col2 = it + SUM(nreh) 937 exc_ham(row2,col2) = cttp ! lower reso. 938 end do 939 end do 940 ! 941 end if 942 943 CASE DEFAULT 944 ABI_ERROR("Unknown block_type: "//TRIM(block_type)) 945 END SELECT 946 947 ABI_FREE(cbuff_dpc) 948 949 return 950 951 ! Handle IO Error 952 10 continue 953 ABI_ERROR(errmsg) 954 955 end subroutine exc_fullh_from_blocks
m_bse_io/exc_read_bshdr [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
exc_read_bshdr
FUNCTION
Reads the header of the (BSR|BSC) files storing the excitonic Hamiltonian. and performs basilar consistency checks.
INPUTS
funt=Unit number. Bsp<excparam>=Structure storing the parameters of the run. Hdr<hdr_type>=The abinit header.
OUTPUT
fform=Integer defining the file format. ierr=Status error.
SOURCE
138 subroutine exc_read_bshdr(funt,Bsp,fform,ierr) 139 140 !Arguments ------------------------------------ 141 integer,intent(in) :: funt 142 integer,intent(out) :: fform,ierr 143 type(excparam),intent(in) :: BSp 144 145 !Local variables ------------------------------ 146 !scalars 147 integer :: nkbz_read 148 character(len=500) :: errmsg 149 type(hdr_type) :: Hdr 150 !arrays 151 integer :: nreh_read(SIZE(BSp%nreh)) 152 153 ! ************************************************************************* 154 155 ierr=0 156 157 ! Read the header and perform consistency checks. 158 call hdr_fort_read(hdr, funt, fform, rewind=.True.) 159 ABI_CHECK(fform /= 0, "hdr_fort_read returned fform == 0") 160 161 read(funt, err=10, iomsg=errmsg) nreh_read, nkbz_read 162 163 call Hdr%free() 164 165 if (ANY(nreh_read/=BSp%nreh)) then 166 call wrtout(std_out,"Wrong number of e-h transitions","COLL") 167 ierr = ierr + 1 168 end if 169 170 return 171 172 10 ierr = 1 173 ABI_WARNING(errmsg) 174 175 end subroutine exc_read_bshdr
m_bse_io/exc_read_eigen [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
exc_read_eigen
FUNCTION
Read selected energies and eigenvectors from the BSEIG file.
INPUTS
eig_fname=The name of the file storing the excitonic eigenvectors. hsize=Size of the Hamiltonian. nvec=Number of excitonic states to analyze. vec_idx(nvec)=List with the indices of the excitonic states sorted in ascending order. [Bsp]<excparam>=Structure storing the parameters of the run. If present the routine will perform additional consistency checks to make sure that the content of the file is consistent with the present run.
OUTPUT
[ene_list(nvec)]=Excitonic energies vec_list(hsize,nvec)=Excitonic eigenvectors.
SOURCE
291 subroutine exc_read_eigen(eig_fname,hsize,nvec,vec_idx,vec_list,ene_list,Bsp) 292 293 !Arguments ------------------------------------ 294 !scalars 295 integer,intent(in) :: nvec,hsize 296 character(len=*),intent(in) :: eig_fname 297 type(excparam),optional,intent(in) :: BSp 298 ! arrays 299 integer,intent(in) :: vec_idx(nvec) 300 real(dp),optional,intent(out) :: ene_list(nvec) 301 complex(dpc),intent(out) :: vec_list(hsize,nvec) 302 303 !Local variables ------------------------------ 304 !scalars 305 integer :: eig_unt,hsize_read,neig_read,ll,vec 306 character(len=500) :: msg,errmsg 307 !arrays 308 !real(dp),allocatable :: exc_ene(:) 309 complex(dpc),allocatable :: exc_ene_cplx(:) 310 311 ! ************************************************************************* 312 313 ABI_UNUSED(BSp%nline) 314 315 if (open_file(eig_fname,msg,newunit=eig_unt,form="unformatted",status="old",action="read") /= 0) then 316 ABI_ERROR(msg) 317 end if 318 319 read(eig_unt, err=10, iomsg=errmsg)hsize_read,neig_read 320 !write(std_out,*)hsize_read, neig_read 321 322 if (hsize_read/=hsize) then 323 write(msg,'(a,2(1x,i0))')" hsize_read/=hsize: ",hsize_read,hsize 324 ABI_ERROR(msg) 325 end if 326 327 ! Read eigenvalues, ignore possibly small imaginary part. 328 ABI_MALLOC(exc_ene_cplx,(neig_read)) 329 read(eig_unt, err=10, iomsg=errmsg) exc_ene_cplx 330 331 if (PRESENT(ene_list)) then 332 do vec=1,nvec 333 ll = vec_idx(vec) 334 ene_list(vec) = DBLE(exc_ene_cplx(ll)) 335 end do 336 end if 337 ABI_FREE(exc_ene_cplx) 338 339 vec=1 340 do ll=1,neig_read ! Read the selected excitons. 341 if (ll==vec_idx(vec)) then 342 read(eig_unt, err=10, iomsg=errmsg) vec_list(:,vec) 343 if (vec==nvec) EXIT 344 vec=vec+1 345 else 346 read(eig_unt, err=10, iomsg=errmsg) 347 end if 348 end do 349 350 close(eig_unt, err=10, iomsg=errmsg) 351 352 if (vec/=nvec) then 353 write(msg,'(a,2(1x,i0))')" vec_idx is wrong, vec/=nvec ",vec,nvec+1 354 ABI_ERROR(msg) 355 end if 356 357 return 358 359 ! Handle IO-error 360 10 continue 361 ABI_ERROR(errmsg) 362 363 end subroutine exc_read_eigen
m_bse_io/exc_read_rblock_fio [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
exc_read_rblock_fio
FUNCTION
Reads the resonant block from file using Fortran IO.
INPUTS
funt=Fortran unit number. nsppol=Number of spins exc_size=Size of the resonant bock. diago_is_real=.TRUE. if diagonal elements are real. nreh(nsppol)=Number of resonant transitions for each spin.
OUTPUT
ierr=Status error exc_mat(exc_size,exc_size)=The resonant block.
SOURCE
1118 subroutine exc_read_rblock_fio(funt,diago_is_real,nsppol,nreh,exc_size,exc_mat,ierr) 1119 1120 !Arguments ------------------------------------ 1121 !scalars 1122 integer,intent(in) :: funt,nsppol,exc_size 1123 logical,intent(in) :: diago_is_real 1124 integer,intent(out) :: ierr 1125 !arrays 1126 integer,intent(in) :: nreh(nsppol) 1127 complex(dpc),intent(out) :: exc_mat(exc_size,exc_size) 1128 1129 !Local variables ------------------------------ 1130 !scalars 1131 integer :: itp,it,block,col,row,spad 1132 complex(dpc) :: ctemp 1133 character(len=500) :: errmsg 1134 !arrays 1135 complex(dpc),allocatable :: cbuff_dpc(:) 1136 1137 ! ************************************************************************* 1138 1139 ierr=0 1140 1141 ! Construct full resonant block using Hermiticity. File is always in double precision. 1142 ABI_MALLOC(cbuff_dpc,(exc_size)) 1143 1144 if (nsppol==1) then ! Construct resonant block from the upper triangle stored on file. 1145 ! 1146 do itp=1,nreh(1) 1147 read(funt, err=10, iomsg=errmsg) cbuff_dpc(1:itp) 1148 do it=1,itp-1 ! Diagonal is treated below. 1149 ctemp = cbuff_dpc(it) 1150 exc_mat(it,itp) = ctemp 1151 exc_mat(itp,it) = CONJG(ctemp) 1152 end do 1153 if (diago_is_real) then 1154 exc_mat(itp,itp) = DBLE(cbuff_dpc(itp)) 1155 else 1156 exc_mat(itp,itp) = cbuff_dpc(itp) 1157 end if 1158 end do 1159 ! 1160 else 1161 ! The file contains 1162 ! A) The up-up and the down-down block in packed form 1163 ! (only the upper triangle is stored since these blocks are Hermitian) 1164 ! B) The entire up-down exchange block (no symmetry here) 1165 ! 1166 ! A) Construct resonant blocks from the upper triangles stored on file. 1167 ! FIXME this part wont work if we have a different number of e-h pairs 1168 !ABI_CHECK(ALL(nreh==nreh(1)),"Different number of transitions") 1169 1170 do block=1,2 1171 if (block==1) spad=0 1172 if (block==2) spad=nreh(1) 1173 do itp=1,nreh(block) 1174 read(funt, err=10, iomsg=errmsg) cbuff_dpc(1:itp) 1175 col = itp+spad 1176 do it=1,itp-1 ! diagonal is treated below. 1177 ctemp = cbuff_dpc(it) 1178 row = it + spad 1179 exc_mat(row,col) = ctemp 1180 exc_mat(col,row) = CONJG(ctemp) 1181 end do 1182 if (diago_is_real) then 1183 exc_mat(col,col) = DBLE(cbuff_dpc(itp)) 1184 else 1185 exc_mat(col,col) = cbuff_dpc(itp) 1186 end if 1187 end do 1188 end do 1189 ! 1190 ! read v+- that is a matrix with shape nreh(1) X nreh(2) 1191 spad=nreh(1) 1192 do itp=1,nreh(2) 1193 read(funt, err=10, iomsg=errmsg) cbuff_dpc(1:nreh(1)) 1194 exc_mat(1:nreh(1),spad+itp) = cbuff_dpc(1:nreh(1)) 1195 end do 1196 1197 end if 1198 1199 ABI_FREE(cbuff_dpc) 1200 1201 return 1202 1203 ! Raise the error. 1204 10 continue 1205 ierr = 1 1206 ABI_WARNING(errmsg) 1207 1208 end subroutine exc_read_rblock_fio
m_bse_io/exc_read_rcblock [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
exc_read_rcblock
FUNCTION
Reads the excitonic Hamiltonian from file
INPUTS
fname=File name. diago_is_real=.TRUE. if diagonal elements are real (used only if is_resonant==.TRUE.) nreh(nsppol)=Number of resonant transition for the two spins. is_resonant=Set to .TRUE. if the block is resonant. hsize=Dimension of the block. nsppol=2 for spin polarized systems. 1 otherwise. my_t1,my_t2=The first and the last colums of the matrix treated by this node. use_mpio=.TRUE. is MPI-IO routines are used. comm=MPI communicator.
OUTPUT
hmat(hsize,my_t1:my_t2)=The block read from file fname.
TODO
Remove Bsp
SOURCE
394 subroutine exc_read_rcblock(fname,Bsp,is_resonant,diago_is_real,nsppol,nreh,hsize,my_t1,my_t2,hmat,use_mpio,comm) 395 396 !Arguments ------------------------------------ 397 !scalars 398 integer,intent(in) :: comm,hsize,my_t1,my_t2,nsppol 399 logical,intent(in) :: is_resonant,use_mpio,diago_is_real 400 character(len=*),intent(in) :: fname 401 type(excparam),intent(in) :: Bsp 402 !arrays 403 integer,intent(in) :: nreh(nsppol) 404 complex(dpc),intent(out) :: hmat(hsize,my_t1:my_t2) 405 406 !Local variables ------------------------------ 407 !scalars 408 integer,parameter :: master=0 409 integer :: it,itp,funit,nproc,my_rank,neh1,neh2 410 integer :: fform,my_nt 411 integer :: row,col,block,spad,spin_dim,ierr,size_exp 412 real(dp) :: cputime,walltime,gflops 413 character(len=500) :: msg,errmsg 414 !type(Hdr_type) :: bse_Hdr 415 !arrays 416 complex(dpc),allocatable :: buffer_dpc(:) 417 logical :: have_row,have_col 418 #ifdef HAVE_MPI_IO 419 integer :: mpierr,mpifh,ham_type,my_nel,old_type,etype,offset_err,amode 420 integer :: irec,nrec !,ncount 421 integer(XMPI_OFFSET_KIND) :: ehdr_offset,my_offset,my_offpad,fsize 422 integer(XMPI_OFFSET_KIND),allocatable :: bsize_frecord(:) 423 integer :: glob_sizes(2),my_cols(2) 424 integer :: block_sizes(2,3) 425 integer :: status(MPI_STATUS_SIZE) 426 #endif 427 428 !************************************************************************ 429 430 nproc = xmpi_comm_size(comm); my_rank= xmpi_comm_rank(comm) 431 432 ! Compute the (Expected) size of the hamiltonian. 433 neh1 = nreh(1) 434 neh2 = neh1; if (nsppol==2) neh2=nreh(2) 435 436 size_exp=neh1; if (nsppol==2) size_exp=SUM(nreh) 437 438 ABI_CHECK(hsize==size_exp,"Wrong hsize") 439 if (neh1/=neh2) then 440 msg = "BSE code does not support different number of transitions for the two spin channels" 441 ABI_ERROR(msg) 442 end if 443 444 my_nt = my_t2-my_t1+1 445 446 !BEGINDEBUG 447 ! hmat = HUGE(zero) 448 !ENDDEBUG 449 450 if (.not.use_mpio) then 451 452 if (is_resonant) then 453 call wrtout(std_out,". Reading resonant block from file: "//TRIM(fname)//" using Fortran-IO","COLL") 454 else 455 call wrtout(std_out,". Reading coupling block from file: "//TRIM(fname)//" using Fortran-IO","COLL") 456 end if 457 458 if (open_file(fname,msg,newunit=funit,form="unformatted",status="old",action="read") /= 0) then 459 ABI_ERROR(msg) 460 end if 461 ! 462 ! Read the header and perform consistency checks. 463 call exc_read_bshdr(funit,Bsp,fform,ierr) 464 ABI_CHECK(ierr==0,"Wrong BSE header") 465 ! 466 ! Construct full excitonic Hamiltonian using symmetries. 467 if (nsppol==1) then 468 call cwtime(cputime,walltime,gflops,"start") 469 ! 470 ABI_MALLOC(buffer_dpc,(neh1)) 471 do itp=1,hsize 472 read(funit, err=10, iomsg=errmsg) buffer_dpc(1:itp) 473 ! 474 ! Fill the upper triangle if I have this column. 475 if (itp>=my_t1 .and. itp<=my_t2) then 476 do it=1,itp 477 hmat(it,itp) = buffer_dpc(it) 478 end do 479 ! Force the diagonal to be real. 480 if (is_resonant .and.diago_is_real) hmat(itp,itp) = DBLE(hmat(itp,itp)) 481 end if 482 ! 483 ! Reconstruct the rows below the diagonal (diagonal part is not touched here). 484 if (is_resonant) then ! Use Hermiticity. 485 do it=1,itp-1 486 if (it>=my_t1 .and. it<=my_t2) hmat(itp,it) = CONJG(buffer_dpc(it)) 487 end do 488 else ! Coupling is symmetric. 489 do it=1,itp-1 490 if (it>=my_t1 .and. it<=my_t2) hmat(itp,it) = buffer_dpc(it) 491 end do 492 end if 493 ! 494 end do ! itp 495 ABI_FREE(buffer_dpc) 496 497 call cwtime(cputime,walltime,gflops,"stop") 498 write(msg,'(2(a,f9.1),a)')" Fortran-IO completed. cpu_time ",cputime,"[s], walltime ",walltime," [s]" 499 call wrtout(std_out,msg,"COLL", do_flush=.True.) 500 else 501 ! Spin polarized case. 502 ! 503 ! The file contains 504 ! A) The up-up and the down-down block in packed form 505 ! (only the upper triangle is stored since the blocks are Hermitian) 506 ! B) The entire up-down exchange block (no symmetry here) 507 ! 508 ! A) Construct resonant blocks from the upper triangles stored on file. 509 ! FIXME this part wont work if we have a different number of e-h pairs 510 if (.not.is_resonant) then 511 ABI_ERROR("exc_read_rcblock does not support coupling.") 512 end if 513 ! It should be checked. 514 spin_dim=neh1 515 do block=1,2 516 ABI_MALLOC(buffer_dpc,(neh1)) 517 if (block==1) spad=0 518 if (block==2) spad=neh1 519 do itp=1,spin_dim 520 ! 521 read(funit, err=10, iomsg=errmsg) buffer_dpc(1:itp) 522 ! 523 ! Fill the upper triangle if this node treats this column 524 col = itp+spad 525 if (col>=my_t1 .and. col<=my_t2) then 526 do it=1,itp 527 row = it + spad 528 hmat(row,col) = buffer_dpc(it) 529 end do 530 ! Force the diagonal to be real. 531 if (is_resonant .and.diago_is_real) hmat(col,col) = DBLE(hmat(col,col)) 532 end if 533 ! 534 ! Reconstruct the rows below the diagonal (diagonal part is not touched here). 535 row = itp + spad 536 if (is_resonant) then ! Hermitian 537 do it=1,itp-1 538 col = it + spad 539 if (col>=my_t1 .and. col<=my_t2) hmat(row,col) = CONJG(buffer_dpc(it)) 540 end do 541 else ! Coupling is symmetric. 542 do it=1,itp-1 543 col = it + spad 544 if (col>=my_t1 .and. col<=my_t2) hmat(row,col) = buffer_dpc(it) 545 end do 546 end if 547 ! 548 end do ! itp 549 ABI_FREE(buffer_dpc) 550 end do ! block 551 ! 552 ! B) Kx_{down up} = Kx_{up down}^H. 553 ! FIXME this part wont work if we have a different number of e-h pairs 554 spad=neh1 555 spin_dim=neh1 556 ABI_MALLOC(buffer_dpc,(neh1)) 557 do itp=1,spin_dim 558 read(funit, err=10, iomsg=errmsg) buffer_dpc(1:spin_dim) 559 have_col = (spad+itp>=my_t1 .and. spad+itp<=my_t2) 560 if (have_col) hmat(1:spin_dim,spad+itp) = buffer_dpc(1:spin_dim) 561 ! Construct and store the lower block 562 if (is_resonant) then ! Hermitian 563 do it=1,spin_dim 564 have_row = (it>=my_t1 .and. it<=my_t2) 565 if (have_row) hmat(spad+itp,it) = CONJG(buffer_dpc(it)) 566 end do 567 else ! Symmetric 568 do it=1,spin_dim 569 have_row = (it>=my_t1 .and. it<=my_t2) 570 if (have_row) hmat(spad+itp,it) = buffer_dpc(it) 571 end do 572 end if 573 end do 574 ABI_FREE(buffer_dpc) 575 end if 576 577 close(funit) 578 579 else 580 #ifdef HAVE_MPI_IO 581 if (is_resonant) then 582 call wrtout(std_out,". Reading resonant block from file "//TRIM(fname)//" using MPI-IO","COLL") 583 else 584 call wrtout(std_out,". Reading coupling block from file "//TRIM(fname)//" using MPI-IO","COLL") 585 end if 586 587 amode=MPI_MODE_RDONLY 588 call MPI_FILE_OPEN(comm,fname,amode,MPI_INFO_NULL,mpifh,mpierr) 589 msg = " FILE_OPEN "//TRIM(fname) 590 ABI_CHECK_MPI(mpierr,msg) 591 592 call MPI_FILE_GET_SIZE(mpifh,fsize,mpierr) 593 write(std_out,*)" file size is ",fsize 594 ! 595 ! Skip the header and find the offset for reading the matrix. 596 call exc_skip_bshdr_mpio(mpifh,xmpio_collective,ehdr_offset) 597 ! 598 ! Read my columns from file. 599 old_type=MPI_DOUBLE_COMPLEX 600 glob_sizes = (/hsize,hsize/); my_cols=(/my_t1,my_t2/) 601 602 if (nsppol==1) then 603 call xmpio_create_coldistr_from_fpacked(glob_sizes,my_cols,old_type,ham_type,my_offpad,offset_err) 604 else 605 ABI_WARNING("nsppol==2 => calling fp3blocks") 606 write(std_out,*)"neh, hsize",neh1,neh2,hsize 607 608 #if 1 609 nrec=neh1+2*neh2 610 ABI_MALLOC(bsize_frecord,(nrec)) 611 bsize_frecord(1:neh1) = (/(irec*xmpi_bsize_dpc, irec=1,neh1)/) 612 bsize_frecord(neh1+1:neh1+neh2) = (/(irec*xmpi_bsize_dpc, irec=1,neh2)/) 613 bsize_frecord(neh1+neh2+1:) = neh1*xmpi_bsize_dpc 614 call xmpio_check_frmarkers(mpifh,ehdr_offset,xmpio_collective,nrec,bsize_frecord,ierr) 615 ABI_CHECK(ierr==0,"Error in Fortran markers") 616 ABI_FREE(bsize_frecord) 617 ABI_COMMENT("Marker check ok") 618 call xmpi_barrier(comm) 619 #endif 620 621 block_sizes(:,1) = (/neh1,neh1/) 622 block_sizes(:,2) = (/neh2,neh2/) 623 block_sizes(:,3) = (/neh1,neh2/) 624 ABI_ERROR("fp3blocks is buggy") 625 call xmpio_create_coldistr_from_fp3blocks(glob_sizes,block_sizes,my_cols,old_type,ham_type,my_offpad,offset_err) 626 end if 627 628 if (offset_err/=0) then 629 write(msg,"(3a)")& 630 & "Global position index cannot be stored in a standard Fortran integer ",ch10,& 631 & "Excitonic matrix cannot be read with a single MPI-IO call." 632 ABI_ERROR(msg) 633 end if 634 ! 635 ! The offset used for reading. 636 my_offset = ehdr_offset + my_offpad 637 write(std_out,*)"my_offset= ",my_offset 638 639 etype=MPI_BYTE 640 call MPI_FILE_SET_VIEW(mpifh, my_offset, etype, ham_type, 'native', MPI_INFO_NULL, mpierr) 641 ABI_CHECK_MPI(mpierr,"SET_VIEW") 642 ! 643 ! Release the MPI filetype. 644 call MPI_TYPE_FREE(ham_type,mpierr) 645 ABI_CHECK_MPI(mpierr,"TYPE_FREE") 646 647 my_nel = my_nt*hsize 648 call MPI_FILE_READ_ALL(mpifh, hmat, my_nel, MPI_DOUBLE_COMPLEX, status, mpierr) 649 ABI_CHECK_MPI(mpierr,"READ_ALL") 650 651 !call MPI_GET_COUNT(status, MPI_DOUBLE_COMPLEX, ncount, mpierr) 652 !write(std_out,*)"count, my_nel ",ncount,my_nel 653 !ABI_CHECK_MPI(mpierr,"READ_ALL") 654 ! 655 ! Close the file. 656 call MPI_FILE_CLOSE(mpifh, mpierr) 657 ABI_CHECK_MPI(mpierr,"FILE_CLOSE") 658 ! 659 ! Use the symmetries of the block to reconstruct the local buffer. 660 ! Coupling does not require in-place symmetrization since it is symmetric. 661 if (is_resonant) then 662 do itp=my_t1,my_t2 663 if (itp+1<=hsize) hmat(itp+1:,itp) = DCONJG(hmat(itp+1:,itp)) ! Lower triangle using Hermiticity. 664 if (diago_is_real) hmat(itp,itp) = DBLE(hmat(itp,itp)) ! The diagonal is forced to be real when energies are real. 665 end do 666 end if 667 668 call xmpi_barrier(comm) 669 #else 670 ABI_ERROR("MPI-IO support not enabled") 671 #endif 672 end if 673 674 !BEGINDEBUG 675 ! if ( ANY(hmat==HUGE(zero)) ) then 676 ! write(std_out,*)"COUNT",COUNT(hmat==HUGE(zero))," hsize= ",hsize 677 ! ABI_ERROR("Something wrong in the reading") 678 ! end if 679 !ENDDEBUG 680 681 call xmpi_barrier(comm) 682 683 return 684 685 ! Handle IO Error 686 10 continue 687 ABI_ERROR(errmsg) 688 689 end subroutine exc_read_rcblock
m_bse_io/exc_skip_bshdr [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
exc_skip_bshdr
FUNCTION
Skip the header of the (BSR|BSC) files storing the excitonic Hamiltonian. Fortran version.
INPUTS
funt=Unit number.
OUTPUT
ierr=Status error.
SIDE EFFECTS
Skip the header.
SOURCE
198 subroutine exc_skip_bshdr(funt,ierr) 199 200 !Arguments ------------------------------------ 201 integer,intent(in) :: funt 202 integer,intent(out) :: ierr 203 204 !Local variables------------------------------- 205 character(len=500) :: errmsg 206 ! ************************************************************************* 207 208 call hdr_skip(funt,ierr) 209 if (ierr/=0) RETURN 210 read(funt, err=10, iomsg=errmsg) 211 212 return 213 214 ! Handle IO Error 215 10 continue 216 ierr = 0 217 ABI_WARNING(errmsg) 218 219 end subroutine exc_skip_bshdr
m_bse_io/exc_skip_bshdr_mpio [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
exc_skip_bshdr_mpio
FUNCTION
Skip the header of the (BSR|BSC) files storing the excitonic Hamiltonian. MPI-IO version.
INPUTS
mpifh=MPI-IO file handler. at_option
SIDE EFFECTS
ehdr_offset
SOURCE
240 subroutine exc_skip_bshdr_mpio(mpifh,at_option,ehdr_offset) 241 242 !Arguments ------------------------------------ 243 integer,intent(in) :: mpifh,at_option 244 integer(XMPI_OFFSET_KIND),intent(inout) :: ehdr_offset 245 246 !Local variables ------------------------------ 247 !scalars 248 integer :: fform,ierr 249 #ifdef HAVE_MPI_IO 250 integer(XMPI_OFFSET_KIND) :: fmarker 251 #endif 252 253 ! ************************************************************************* 254 255 call hdr_mpio_skip(mpifh,fform,ehdr_offset) 256 257 #ifdef HAVE_MPI_IO 258 call xmpio_read_frm(mpifh,ehdr_offset,at_option,fmarker,ierr) 259 !write(std_out,*)"fmarker last record ",fmarker 260 #else 261 ABI_ERROR("You should not be here") 262 #endif 263 264 end subroutine exc_skip_bshdr_mpio
m_bse_io/exc_write_bshdr [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
exc_write_bshdr
FUNCTION
Writes the header of the (BSR|BSC) files storing the excitonic Hamiltonian.
INPUTS
funt=Fortran unit number. Bsp<excparam>=Structure storing the parameters of the run. Hdr<hdr_type>=The abinit header.
OUTPUT
Only writing
SOURCE
90 subroutine exc_write_bshdr(funt,Bsp,Hdr) 91 92 !Arguments ------------------------------------ 93 integer,intent(in) :: funt 94 type(excparam),intent(in) :: BSp 95 type(hdr_type),intent(inout) :: Hdr 96 97 !Local variables ------------------------------ 98 !scalars 99 integer :: fform_1002 = 1002 ! TODO: change setup_bse so that Hdr_bse reflects the parameters of the run. 100 integer :: ierr 101 character(len=500) :: errmsg 102 ! ************************************************************************* 103 104 call hdr%fort_write(funt, fform_1002, ierr) 105 ABI_CHECK(ierr == 0, "hdr_fort_write returned ierr != 0") 106 write(funt, err=10, iomsg=errmsg) BSp%nreh,BSp%nkbz 107 108 return 109 110 ! Handle IO Error 111 10 continue 112 ABI_ERROR(errmsg) 113 114 end subroutine exc_write_bshdr
m_bse_io/exc_write_optme [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
exc_write_optme
FUNCTION
Writes the optical matrix elements in the OME.nc file. Note that this is only available when NetCDF is available
INPUTS
filname=filename used to write the optical matrix elements minb,maxb=minimum and max band index that have been calculated. nkbz=Number of points in the full Brillouin zone. nsppol=Number of independent spin polarizations. nq=Number of "small" q for optical limit. opt_cvk=Optical matrix elements to be written
OUTPUT
ierr=return status of the writing process. => 0 if everything was ok => -1 if NetCDF is not available => 1 if NetCDF is available
SOURCE
1370 subroutine exc_write_optme(filname,minb,maxb,nkbz,nsppol,nq,opt_cvk,ierr) 1371 1372 !Arguments ------------------------------------ 1373 integer,intent(in) :: minb,maxb,nkbz,nsppol,nq 1374 character(len=fnlen),intent(in) :: filname 1375 complex(dpc),intent(in) :: opt_cvk(minb:maxb,minb:maxb,nkbz,nsppol,nq) 1376 integer,intent(out) :: ierr 1377 1378 !Local variables ------------------------------ 1379 !scalars 1380 integer :: ncid,cmplx_id,nband_id,nkbz_id,nsppol_id,nq_id,xyz_id 1381 integer :: minb_id,maxb_id,ome_id,iq,is,ik,ib,jb 1382 integer :: dimOME(6),dimKPT(2),dimQPT(2),dimSCA(0),start6(6),count6(6) 1383 real(dp) :: complex2(2) 1384 ! ************************************************************************* 1385 1386 ierr = 1 1387 1388 !1. Create netCDF file 1389 NCF_CHECK_MSG(nctk_open_create(ncid, filname, xmpi_comm_self), " create netcdf OME file") 1390 1391 !2. Define dimensions 1392 NCF_CHECK(nf90_def_dim(ncid,"xyz",3,xyz_id)) 1393 NCF_CHECK(nf90_def_dim(ncid,"cmplx",2,cmplx_id)) 1394 NCF_CHECK(nf90_def_dim(ncid,"nband",maxb-minb+1,nband_id)) 1395 NCF_CHECK(nf90_def_dim(ncid,"nkbz",nkbz,nkbz_id)) 1396 NCF_CHECK(nf90_def_dim(ncid,"nq",nq,nq_id)) 1397 NCF_CHECK(nf90_def_dim(ncid,"nsppol",nsppol,nsppol_id)) 1398 1399 !Dimensions for optical matrix elements 1400 dimOME = (/ cmplx_id, nband_id, nband_id, nkbz_id, nsppol_id, nq_id /) 1401 !Dimensions for kpoint positions 1402 dimKPT = (/ xyz_id, nkbz_id /) 1403 !Dimensions for qpoints for the optical limit 1404 dimQPT = (/ xyz_id, nq_id /) 1405 1406 !3. Define variables 1407 1408 call ab_define_var(ncid, dimOME, ome_id, NF90_DOUBLE,& 1409 "OME", "Values of optical matrix elements","Tobedone") 1410 1411 call ab_define_var(ncid, dimSCA, minb_id, NF90_INT,"minb",& 1412 "Minimum band index for the optical matrix elements", "Dimensionless") 1413 1414 call ab_define_var(ncid, dimSCA, maxb_id, NF90_INT,"maxb",& 1415 "Maximum band index for the optical matrix elements", "Dimensionless") 1416 1417 !4. End define mode 1418 NCF_CHECK(nf90_enddef(ncid)) 1419 1420 !5 Write scalars (minb and maxb) 1421 1422 NCF_CHECK(nf90_put_var(ncid, minb_id, minb)) 1423 NCF_CHECK(nf90_put_var(ncid, maxb_id, maxb)) 1424 1425 !6 Write optical matrix elements 1426 1427 do iq=1,nq 1428 do is=1,nsppol 1429 do ik=1,nkbz 1430 do ib=minb,maxb 1431 do jb=minb,maxb 1432 start6 = (/ 1, ib-minb+1, jb-minb+1, ik, is, iq /) 1433 count6 = (/ 2, 1, 1, 1, 1, 1 /) 1434 complex2 = (/ REAL(opt_cvk(ib,jb,ik,is,iq)),AIMAG(opt_cvk(ib,jb,ik,is,iq)) /) 1435 NCF_CHECK(nf90_put_var(ncid, ome_id, complex2, start = start6, count = count6)) 1436 end do 1437 end do 1438 end do 1439 end do 1440 end do 1441 1442 !7 Close file 1443 NCF_CHECK(nf90_close(ncid)) 1444 ierr = 0 1445 1446 end subroutine exc_write_optme
m_bse_io/offset_in_file [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
offset_in_file
FUNCTION
Return the offset of the matrix element (row_glob,col_glob) size_glob(2) gives the number of row and column of the global matrix nsblocks is the number of sublocks, used for nsppol==2 (not used if 1) sub_block(2,2,nsblocks)= For each subblock the coordinates of the first and last element.
INPUTS
OUTPUT
SOURCE
1060 function offset_in_file(row_glob,col_glob,size_glob,nsblocks,sub_block,bsize_elm,bsize_frm) 1061 1062 !Arguments ------------------------------------ 1063 integer(XMPI_OFFSET_KIND) :: offset_in_file 1064 integer,intent(in) :: row_glob,col_glob,nsblocks,bsize_elm,bsize_frm 1065 integer,intent(in) :: size_glob(2),sub_block(2,2,nsblocks) 1066 1067 !Local variables ------------------------------ 1068 !scalars 1069 integer :: ii,jj,ijp_glob,swap 1070 integer(XMPI_OFFSET_KIND) :: my_offset 1071 1072 ! ************************************************************************* 1073 1074 if (nsblocks==1) then 1075 ii = row_glob 1076 jj = col_glob 1077 if (ii>size_glob(1)/2) ii = ii - size_glob(1)/2 ! Wrap the index. 1078 if (jj>size_glob(2)/2) jj = jj - size_glob(2)/2 1079 if (jj<ii) then ! Exchange the indices since the symmetric element is read. 1080 swap = jj 1081 jj = ii 1082 ii = swap 1083 end if 1084 ijp_glob = ii + jj*(jj-1)/2 ! Index for packed storage mode. 1085 my_offset = (ijp_glob-1)*bsize_elm + (jj-1)*2*bsize_frm 1086 else 1087 ABI_UNUSED(sub_block(1,1,1)) 1088 ABI_ERROR("nsppol==2 not coded") 1089 end if 1090 1091 offset_in_file = my_offset 1092 1093 end function offset_in_file
m_bse_io/rrs_of_glob [ Functions ]
[ Top ] [ m_bse_io ] [ Functions ]
NAME
rrs_of_glob
FUNCTION
[+1,-1,0] if (row_glob,col_glob) belongs to the [ resonant, anti-resonant, (anti)coupling block ]
INPUTS
OUTPUT
SOURCE
973 pure function rrs_of_glob(row_glob,col_glob,size_glob) 974 975 !Arguments ------------------------------------ 976 integer :: rrs_of_glob 977 integer,intent(in) :: row_glob,col_glob 978 integer,intent(in) :: size_glob(2) 979 980 !Local variables ------------------------------ 981 !scalars 982 integer :: nreh1,nreh2 983 984 ! ************************************************************************* 985 986 nreh1=size_glob(1)/2 ! Matrix is square and nreh1==nreh2 but oh well. 987 nreh2=size_glob(2)/2 988 989 if (row_glob<=nreh1 .and. col_glob<=nreh2) then 990 rrs_of_glob=+1 ! Resonant. 991 else if (row_glob >nreh1 .and. col_glob >nreh2) then 992 rrs_of_glob=-1 ! anti-Resonant. 993 else 994 rrs_of_glob=0 995 end if 996 997 end function rrs_of_glob
m_hexc/exc_ham_ncwrite [ Functions ]
[ Top ] [ m_hexc ] [ Functions ]
NAME
exc_ham_ncwrite
FUNCTION
Writes the content of a hexc object to a NETCDF file according to the ETSF-IO specifications.
INPUTS
ncid =NC file handle
OUTPUT
SOURCE
1466 subroutine exc_ham_ncwrite(ncid,Kmesh,BSp,hsize,nreh,vcks2t,hreso,diag) 1467 1468 !Arguments ------------------------------------ 1469 !scalars 1470 integer,intent(in) :: ncid 1471 integer,intent(in) :: hsize 1472 type(kmesh_t),intent(in) :: Kmesh 1473 type(excparam),intent(in) :: BSp 1474 integer,intent(in) :: nreh(BSp%nsppol) 1475 integer,target,intent(in) :: vcks2t(BSp%maxnbndv,BSp%maxnbndc,Kmesh%nbz,BSp%nsppol) 1476 complex(dpc),target,intent(in) :: hreso(hsize,hsize) 1477 complex(dpc),target,intent(in) :: diag(hsize) 1478 1479 !Local variables------------------------------- 1480 integer :: ncerr 1481 integer :: max_nreh, sum_nreh 1482 real(dp), ABI_CONTIGUOUS pointer :: r2vals(:,:),r3vals(:,:,:) 1483 1484 ! ************************************************************************* 1485 1486 ! ============================================== 1487 ! === Write the dimensions specified by ETSF === 1488 ! ============================================== 1489 max_nreh = MAXVAL(nreh) 1490 sum_nreh = SUM(nreh) 1491 1492 ncerr = nctk_def_dims(ncid, [nctkdim_t("number_of_reduced_dimensions", 3), nctkdim_t("number_of_spins", bsp%nsppol),& 1493 nctkdim_t("number_of_kpoints", kmesh%nbz), nctkdim_t("max_number_of_valence_bands", bsp%maxnbndv),& 1494 nctkdim_t("max_number_of_conduction_bands", bsp%maxnbndc), nctkdim_t("max_number_of_transitions", max_nreh),& 1495 nctkdim_t("total_number_of_transitions", sum_nreh), nctkdim_t("cplex", 2)], defmode=.True.) 1496 NCF_CHECK(ncerr) 1497 1498 ncerr = nctk_def_arrays(ncid, [& 1499 nctkarr_t('vcks2t', "i", 'max_number_of_valence_bands, max_number_of_conduction_bands, number_of_kpoints, number_of_spins'),& 1500 nctkarr_t('hamiltonian', "dp", 'cplex total_number_of_transitions total_number_of_transitions'),& 1501 nctkarr_t('diagonal', "dp", 'cplex total_number_of_transitions'),& 1502 nctkarr_t('lomo', "dp", 'number_of_spins'), & 1503 nctkarr_t('homo', "dp", 'number_of_spins'), & 1504 nctkarr_t('lumo', "dp", 'number_of_spins'), & 1505 nctkarr_t('humo', "dp", 'number_of_spins'), & 1506 nctkarr_t("reduced_coordinates_of_kpoints", "dp", "number_of_reduced_dimensions, number_of_kpoints"), & 1507 nctkarr_t("kpoint_weights", "dp", "number_of_kpoints") & 1508 ]) 1509 NCF_CHECK(ncerr) 1510 1511 ! Write data 1512 NCF_CHECK(nctk_set_datamode(ncid)) 1513 NCF_CHECK(nf90_put_var(ncid, vid('vcks2t'), vcks2t)) 1514 NCF_CHECK(nf90_put_var(ncid, vid('lomo'), BSp%lomo_spin)) 1515 NCF_CHECK(nf90_put_var(ncid, vid('homo'), BSp%homo_spin)) 1516 NCF_CHECK(nf90_put_var(ncid, vid('lumo'), BSp%lumo_spin)) 1517 NCF_CHECK(nf90_put_var(ncid, vid('humo'), BSp%humo_spin)) 1518 1519 call c_f_pointer(c_loc(hreso(1,1)), r3vals, shape=[2, hsize, hsize]) 1520 NCF_CHECK(nf90_put_var(ncid, vid("hamiltonian"), r3vals)) 1521 1522 call c_f_pointer(c_loc(diag(1)), r2vals, shape=[2, hsize]) 1523 NCF_CHECK(nf90_put_var(ncid, vid("diag"), r2vals)) 1524 1525 ! Write K-points 1526 NCF_CHECK(nf90_put_var(ncid, vid("reduced_coordinates_of_kpoints"), kmesh%bz)) 1527 NCF_CHECK(nf90_put_var(ncid, vid("kpoint_weights"), kmesh%wt)) 1528 NCF_CHECK(ncerr) 1529 1530 contains 1531 integer function vid(vname) 1532 character(len=*),intent(in) :: vname 1533 vid = nctk_idname(ncid, vname) 1534 end function vid 1535 1536 end subroutine exc_ham_ncwrite