diff --git a/src/postw90/comms.F90 b/src/postw90/comms.F90 index a9cd4975f..450d1c743 100644 --- a/src/postw90/comms.F90 +++ b/src/postw90/comms.F90 @@ -99,6 +99,7 @@ module w90_comms interface comms_gatherv ! module procedure comms_gatherv_int ! to be done module procedure comms_gatherv_real + module procedure comms_gatherv_logical ! module procedure comms_gatherv_cmplx end interface comms_gatherv @@ -846,6 +847,36 @@ subroutine comms_gatherv_real(array,localcount,rootglobalarray,counts,displs) end subroutine comms_gatherv_real + subroutine comms_gatherv_logical(array,localcount,rootglobalarray,counts,displs) + !! Gather real data to root node + implicit none + + logical, intent(inout) :: array + !! local array for sending data + integer, intent(in) :: localcount + !! localcount elements will be sent to the root node + logical, intent(inout) :: rootglobalarray + !! array on the root node to which data will be sent + integer, dimension(num_nodes), intent(in) :: counts + !! how data should be partitioned, see MPI documentation or + !! function comms_array_split + integer, dimension(num_nodes), intent(in) :: displs + +#ifdef MPI + integer :: error + + call MPI_gatherv(array,localcount,MPI_logical,rootglobalarray,counts,& + displs,MPI_logical,root_id,mpi_comm_world,error) + + if(error.ne.MPI_success) then + call io_error('Error in comms_gatherv_logical') + end if +#else +! rootglobalarray(1:localcount)=array(1:localcount) +#endif + + end subroutine comms_gatherv_logical + subroutine comms_scatterv_real(array,localcount,rootglobalarray,counts,displs) !! Scatter data from root node implicit none diff --git a/src/postw90/kslice.F90 b/src/postw90/kslice.F90 index 624e1fd31..fc44fb3ac 100644 --- a/src/postw90/kslice.F90 +++ b/src/postw90/kslice.F90 @@ -25,10 +25,6 @@ module w90_kslice !! !! kslice_corner(1:3) is the lower left corner !! kslice_b1(1:3) and kslice_b2(1:3) are the vectors subtending the slice - !! - !!--------------------------------- - !! TO DO: Parallelize over k-points - !!--------------------------------- implicit none @@ -62,9 +58,10 @@ subroutine k_slice use w90_berry, only : berry_get_imf_klist,berry_get_imfgh_klist use w90_constants, only : bohr - integer :: itot,i1,i2,n,n1,n2,n3,i - integer :: zdataunit,coorddataunit,& - bandsunit,scriptunit,dataunit + integer, dimension(0:num_nodes-1) :: counts, displs + + integer :: iloc,itot,i1,i2,n,n1,n2,n3,i,nkpts,my_nkpts + integer :: scriptunit real(kind=dp) :: avec_2d(3,3),avec_3d(3,3),bvec(3,3),yvec(3),zvec(3),& b1mod,b2mod,ymod,cosb1b2,kcorner_cart(3),& areab1b2,cosyb2,kpt(3),kpt_x,kpt_y,k1,k2,& @@ -82,23 +79,27 @@ subroutine k_slice complex(kind=dp), allocatable :: UU(:,:) real(kind=dp), allocatable :: eig(:) - ! Everything is done on the root node. However, we still have to - ! read and distribute the data if we are in parallel, so calls to - ! get_oper are done on all nodes - - plot_fermi_lines=.false. - if(index(kslice_task,'fermi_lines')>0) plot_fermi_lines=.true. - plot_curv=.false. - if(index(kslice_task,'curv')>0) plot_curv=.true. - plot_morb=.false. - if(index(kslice_task,'morb')>0) plot_morb=.true. - fermi_lines_color=.false. - if(index(kslice_fermi_lines_colour,'spin')>0) fermi_lines_color=.true. - heatmap=.false. - if(plot_curv .or. plot_morb) heatmap=.true. - if(plot_fermi_lines .and. fermi_lines_color .and. heatmap)& + ! Output data buffers + real(kind=dp), allocatable :: coords(:,:), my_coords(:,:), & + spndata(:,:), my_spndata(:,:), & + bandsdata(:,:), my_bandsdata(:,:), & + zdata(:,:), my_zdata(:,:) + logical, allocatable :: spnmask(:,:), my_spnmask(:,:) + + plot_fermi_lines = index(kslice_task,'fermi_lines') > 0 + plot_curv = index(kslice_task,'curv') > 0 + plot_morb = index(kslice_task,'morb') > 0 + fermi_lines_color = kslice_fermi_lines_colour /= 'none' + heatmap = plot_curv .or. plot_morb + if(plot_fermi_lines .and. fermi_lines_color .and. heatmap) then call io_error('Error: spin-colored Fermi lines not allowed in '& //'curv/morb heatmap plots') + end if + + if(on_root) then + call kslice_print_info(plot_fermi_lines, fermi_lines_color, & + plot_curv, plot_morb) + end if call get_HH_R if(plot_curv.or.plot_morb) call get_AA_R @@ -108,8 +109,6 @@ subroutine k_slice endif if(fermi_lines_color) call get_SS_R - if(on_root) then - ! Set Cartesian components of the vectors (b1,b2) spanning the slice ! bvec(1,:)=matmul(kslice_b1(:),recip_lattice(:,:)) @@ -149,46 +148,14 @@ subroutine k_slice square='False' end if - write(stdout,'(/,/,1x,a)')& - 'Properties calculated in module k s l i c e' - write(stdout,'(1x,a)')& - '--------------------------------------------' - - if(plot_fermi_lines) then - if(nfermi/=1) call io_error(& - 'Must specify one Fermi level when kslice_task=fermi_lines') - select case(fermi_lines_color) - case(.false.) - write(stdout,'(/,3x,a)') '* Fermi lines' - case(.true.) - write(stdout,'(/,3x,a)') '* Fermi lines coloured by spin' - end select - write(stdout,'(/,7x,a,f10.4,1x,a)')& - '(Fermi level: ',fermi_energy_list(1),'eV)' - endif - if(plot_curv) then - if(berry_curv_unit=='ang2') then - write(stdout,'(/,3x,a)') '* Negative Berry curvature in Ang^2' - elseif(berry_curv_unit=='bohr2') then - write(stdout,'(/,3x,a)') '* Negative Berry curvature in Bohr^2' - endif - if(nfermi/=1) call io_error(& - 'Must specify one Fermi level when kslice_task=curv') - elseif(plot_morb) then - write(stdout,'(/,3x,a)')& - '* Orbital magnetization k-space integrand in eV.Ang^2' - if(nfermi/=1) call io_error(& - 'Must specify one Fermi level when kslice_task=morb') - endif + nkpts = (kslice_2dkmesh(1)+1)*(kslice_2dkmesh(2)+1) - write(stdout,'(/,/,1x,a)') 'Output files:' + ! Partition set of k-points into junks + call comms_array_split(nkpts, counts, displs); + my_nkpts = counts(my_node_id) - if(.not.fermi_lines_color) then - coorddataunit=io_file_unit() - filename=trim(seedname)//'-kslice-coord.dat' - write(stdout,'(/,3x,a)') filename - open(coorddataunit,file=filename,form='formatted') - endif + allocate(my_coords(2,my_nkpts)) + if(heatmap) allocate(my_zdata(3,my_nkpts)) if(plot_fermi_lines) then allocate(HH(num_wann,num_wann)) @@ -196,47 +163,19 @@ subroutine k_slice allocate(eig(num_wann)) if(fermi_lines_color) then allocate(delHH(num_wann,num_wann,3)) - dataunit=io_file_unit() - filename=trim(seedname)//'-kslice-fermi-spn.dat' - write(stdout,'(/,3x,a)') filename - open(dataunit,file=filename,form='formatted') + allocate(my_spndata(num_wann,my_nkpts)) + allocate(my_spnmask(num_wann,my_nkpts)) + my_spnmask = .false. else - bandsunit=io_file_unit() - filename=trim(seedname)//'-kslice-bands.dat' - write(stdout,'(/,3x,a)') filename - open(bandsunit,file=filename,form='formatted') - if(.not.heatmap) then - allocate(bnddataunit(num_wann)) - do n=1,num_wann - n1=n/100 - n2=(n-n1*100)/10 - n3=n-n1*100-n2*10 - bnddataunit(n)=io_file_unit() - filename=trim(seedname)//'-bnd_'& - //achar(48+n1)//achar(48+n2)//achar(48+n3)//'.dat' - write(stdout,'(/,3x,a)') filename - open(bnddataunit(n),file=filename,form='formatted') - enddo - endif + allocate(my_bandsdata(num_wann,my_nkpts)) endif endif - if(plot_curv) then - zdataunit=io_file_unit() - filename=trim(seedname)//'-kslice-curv.dat' - write(stdout,'(/,3x,a)') filename - open(zdataunit,file=filename,form='formatted') - elseif(plot_morb) then - zdataunit=io_file_unit() - filename=trim(seedname)//'-kslice-morb.dat' - write(stdout,'(/,3x,a)') filename - open(zdataunit,file=filename,form='formatted') - end if - - ! Loop over uniform mesh of k-points covering the slice, + ! Loop over local portion of uniform mesh of k-points covering the slice, ! including all four borders ! - do itot=0,(kslice_2dkmesh(1)+1)*(kslice_2dkmesh(2)+1)-1 + do iloc=1,my_nkpts + itot=iloc-1+displs(my_node_id) i2=itot/(kslice_2dkmesh(1)+1) ! slow i1=itot-i2*(kslice_2dkmesh(1)+1) !fast ! k1 and k2 are the coefficients of the k-point in the basis @@ -254,7 +193,8 @@ subroutine k_slice ! with x along x_vec=b1 and y along y_vec kpt_x=k1*b1mod+k2*b2mod*cosb1b2 kpt_y=k2*b2mod*cosyb2 - if(.not.fermi_lines_color) write(coorddataunit,'(2E16.8)') kpt_x,kpt_y + + my_coords(:,iloc) = [kpt_x, kpt_y] if(plot_fermi_lines) then if(fermi_lines_color) then @@ -272,27 +212,21 @@ subroutine k_slice call pw90common_fourier_R_to_k(kpt,HH_R,HH,0) call utility_diagonalize(HH,num_wann,eig,UU) endif - do n=1,num_wann - if(.not.fermi_lines_color) then - ! For python - write(bandsunit,'(E16.8)') eig(n) - ! For gnuplot, using 'grid data' format - if(.not.heatmap) then - write(bnddataunit(n),'(3E16.8)') kpt_x,kpt_y,eig(n) - if(i1==kslice_2dkmesh(1) .and. i2/=kslice_2dkmesh(2))& - write (bnddataunit(n),*) ' ' - endif - else + + if(allocated(my_bandsdata)) then + my_bandsdata(:,iloc) = eig(:) + else + my_spndata(:,iloc) = spn_k(:) + do n=1,num_wann ! vdum = dE/dk projected on the k-slice zhat=zvec/sqrt(dot_product(zvec,zvec)) vdum(:)=del_eig(n,:)-dot_product(del_eig(n,:),zhat)*zhat(:) Delta_E=sqrt(dot_product(vdum,vdum))*Delta_k ! Delta_E=Delta_E*sqrt(2.0_dp) ! optimize this factor - if(abs(eig(n)-fermi_energy_list(1))