TABLE OF CONTENTS
- ABINIT/m_ioarr
- m_ioarr/denpot_spin_convert
- m_ioarr/fftdatar_write
- m_ioarr/fftdatar_write_from_hdr
- m_ioarr/fort_denpot_skip
- m_ioarr/ioarr
- m_ioarr/read_rhor
ABINIT/m_ioarr [ Modules ]
NAME
m_ioarr
FUNCTION
This module provides routines to read/write arrays given on the FFT mesh (densities, potentials ...). The code supports both Fortran files as well as netcdf files in a transparent way. The appropriate IO layer is selected from files extensions: netcdf primitives are used if the file ends with `.nc`. If all the other cases we read/write files in Fortran format. MPI-IO primitives are used when the FFT arrays are MPI distributed.
COPYRIGHT
Copyright (C) 1998-2024 ABINIT group (DCA, XG, GMR, MVer, MT, 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
20 #if defined HAVE_CONFIG_H 21 #include "config.h" 22 #endif 23 24 #include "abi_common.h" 25 26 MODULE m_ioarr 27 28 use defs_basis 29 use m_abicore 30 use m_xmpi 31 use m_wffile 32 use m_errors 33 use m_nctk 34 use m_dtset 35 use m_crystal 36 use m_ebands 37 use m_hdr 38 use m_pawrhoij 39 #ifdef HAVE_MPI2 40 use mpi 41 #endif 42 use netcdf 43 44 use defs_abitypes, only : mpi_type 45 use defs_datatypes, only : ebands_t 46 use defs_wvltypes, only : wvl_denspot_type 47 use m_time, only : cwtime, cwtime_report, timab 48 use m_io_tools, only : iomode_from_fname, iomode2str, open_file, get_unit 49 use m_fstrings, only : sjoin, itoa, endswith, ltoa 50 use m_numeric_tools, only : interpolate_denpot 51 use m_geometry, only : metric 52 use m_mpinfo, only : destroy_mpi_enreg, ptabs_fourdp, initmpi_seq 53 use m_distribfft, only : init_distribfft_seq 54 use m_fourier_interpol,only : fourier_interpol 55 56 implicit none 57 58 #ifdef HAVE_MPI1 59 include 'mpif.h' 60 #endif 61 62 private 63 64 public :: ioarr ! Read or write rho(r) or v(r), either ground-state or response-functions. 65 public :: fftdatar_write ! Write an array in real space. IO library is automatically selected 66 ! from the file extension and the number of FFT processors: 67 public :: fftdatar_write_from_hdr ! Write an array in real-space to file plus crystal_t and ebands_t 68 public :: read_rhor ! Read rhor from DEN file. 69 public :: fort_denpot_skip ! Skip the header and the DEN/POT records (Fortran format) 70 71 private :: denpot_spin_convert ! Convert a density/potential from a spin representation to another 72 73 CONTAINS !====================================================================================================
m_ioarr/denpot_spin_convert [ Functions ]
[ Top ] [ m_ioarr ] [ Functions ]
NAME
denpot_spin_convert
FUNCTION
Convert a density/potential from a spin representation to another
INPUTS
denpot_in(:,nspden_in)=input density//potential nspden_in=number of spin-component of the input density/potential fform=file format (density or potential) [istart_in]= --optional-- starting index in the denpot_in array; default is 1 [istart_out]= --optional-- starting index in the denpot_out array; default is 1 [nelem]= --optional-- number of elements to copy from denpot_in to denpot_out; default is all
OUTPUT
denpot_out(:,nspden_out)=output density//potential nspden_out=number of spin-component of the output density/potential
NOTES
More explicitely: We copy denpot_in(istar_in+1:istart_in+nelem,:) into denpot_out(istart_out+1:istart_out+nelem,:)
SOURCE
1313 subroutine denpot_spin_convert(denpot_in,nspden_in,denpot_out,nspden_out,fform,& 1314 & istart_in,istart_out,nelem) ! optional arguments 1315 1316 !Arguments ------------------------------------ 1317 !scalars 1318 integer,intent(in) :: nspden_in,nspden_out,fform 1319 integer,intent(in),optional :: istart_in,istart_out,nelem 1320 !arrays 1321 real(dp),intent(in) :: denpot_in(:,:) 1322 real(dp),intent(out) :: denpot_out(:,:) 1323 1324 !Local variables------------------------------- 1325 integer :: iend_in,iend_out,ispden,my_istart_in,my_istart_out,my_nelem 1326 character(len=500) :: msg 1327 1328 ! ********************************************************************* 1329 1330 !Optional arguments 1331 my_istart_in=1;if (present(istart_in)) my_istart_in=istart_in 1332 my_istart_out=1;if (present(istart_out)) my_istart_out=istart_out 1333 iend_in=size(denpot_in,1) ; iend_out=size(denpot_out,1) 1334 my_nelem=min(iend_in-my_istart_in+1,iend_out-my_istart_out+1) 1335 if (present(nelem)) my_nelem=nelem 1336 1337 !Checks 1338 if (size(denpot_in,2)/=nspden_in) then 1339 msg='size(denpot_in,2)/=nspden_in!' 1340 ABI_BUG(msg) 1341 end if 1342 if (size(denpot_out,2)/=nspden_out) then 1343 msg='size(denpot_out,2)/=nspden_out!' 1344 ABI_BUG(msg) 1345 end if 1346 if (my_istart_in+my_nelem-1>size(denpot_in,1)) then 1347 msg='istart_in+nelem>size(denpot_in,1)!' 1348 ABI_BUG(msg) 1349 end if 1350 if (my_istart_out+my_nelem-1>size(denpot_out,1)) then 1351 msg='istart_out+nelem>size(denpot_out,1)!' 1352 ABI_BUG(msg) 1353 end if 1354 1355 !Simple copy if the number of spin-components is unchanged... 1356 if (nspden_in==nspden_out) then 1357 do ispden=1,nspden_in 1358 denpot_out(my_istart_out:my_istart_out+my_nelem-1,ispden)= & 1359 & denpot_in(my_istart_in:my_istart_in+my_nelem-1,ispden) 1360 end do 1361 return 1362 end if 1363 1364 !...otherwise, we need to convert. 1365 if ((fform-1)/2==25) then 1366 1367 ! First case: DENSITY 1368 1369 if (nspden_in==1.and.nspden_out==2) then 1370 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1371 denpot_out(my_istart_out:my_istart_out+my_nelem-1,2)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1)*half 1372 else if (nspden_in==1.and.nspden_out==4) then 1373 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1374 denpot_out(my_istart_out:my_istart_out+my_nelem-1,2)=zero 1375 denpot_out(my_istart_out:my_istart_out+my_nelem-1,3)=zero 1376 denpot_out(my_istart_out:my_istart_out+my_nelem-1,4)=zero 1377 else if (nspden_in==2.and.nspden_out==1) then 1378 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1379 else if (nspden_in==2.and.nspden_out==4) then 1380 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1381 denpot_out(my_istart_out:my_istart_out+my_nelem-1,2)=zero 1382 denpot_out(my_istart_out:my_istart_out+my_nelem-1,3)=zero 1383 denpot_out(my_istart_out:my_istart_out+my_nelem-1,4)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,2)*two & 1384 & -denpot_in(my_istart_in:my_istart_in+my_nelem,1) 1385 else if (nspden_in==4.and.nspden_out==1) then 1386 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1387 else if (nspden_in==4.and.nspden_out==2) then 1388 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1389 denpot_out(my_istart_out:my_istart_out+my_nelem-1,2)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1)*half & 1390 & +denpot_in(my_istart_in:my_istart_in+my_nelem-1,4)*half 1391 end if 1392 1393 else 1394 1395 ! Second case: POTENTIAL 1396 1397 if (nspden_in==1.and.nspden_out==2) then 1398 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1399 denpot_out(my_istart_out:my_istart_out+my_nelem-1,2)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1400 else if (nspden_in==1.and.nspden_out==4) then 1401 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1402 denpot_out(my_istart_out:my_istart_out+my_nelem-1,2)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1403 denpot_out(my_istart_out:my_istart_out+my_nelem-1,3)=zero 1404 denpot_out(my_istart_out:my_istart_out+my_nelem-1,4)=zero 1405 else if (nspden_in==2.and.nspden_out==1) then 1406 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1)*half & 1407 & +denpot_in(my_istart_in:my_istart_in+my_nelem-1,2)*half 1408 else if (nspden_in==2.and.nspden_out==4) then 1409 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1410 denpot_out(my_istart_out:my_istart_out+my_nelem-1,2)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,2) 1411 denpot_out(my_istart_out:my_istart_out+my_nelem-1,3)=zero 1412 denpot_out(my_istart_out:my_istart_out+my_nelem-1,4)=zero 1413 else if (nspden_in==4.and.nspden_out==1) then 1414 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1)*half & 1415 & +denpot_in(my_istart_in:my_istart_in+my_nelem-1,2)*half 1416 else if (nspden_in==4.and.nspden_out==2) then 1417 denpot_out(my_istart_out:my_istart_out+my_nelem-1,1)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,1) 1418 denpot_out(my_istart_out:my_istart_out+my_nelem-1,2)=denpot_in(my_istart_in:my_istart_in+my_nelem-1,2) 1419 end if 1420 1421 end if 1422 1423 end subroutine denpot_spin_convert
m_ioarr/fftdatar_write [ Functions ]
[ Top ] [ m_ioarr ] [ Functions ]
NAME
fftdatar_write
FUNCTION
Write an array in real space on the FFT box to file. The array can be real or complex depending on cplex IO library is automatically selected from the file extension and the number of FFT processors: 1) If path ends with ".nc", the netcdf library is used else Fortran format. 2) If nproc_fft > 1, parallel IO is used (if available)
INPUTS
varname=Name of the variable to write (used if ETSF-IO). path=File name iomode= hdr <type(hdr_type)>=the header of wf, den and pot files crystal<crystal_t>= data type gathering info on symmetries and unit cell (used if etsf_io) ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft cplex=1 for real array, 2 for complex nfft=Number of FFT points treated by this node. nspden=Number of spin-density components. datar(cplex*nfft,nspden)=array on the real space FFT grid. mpi_enreg=information about MPI parallelization [ebands]<ebands_t>=data type with energies and occupations (used if etsf_io)
OUTPUT
Only writing
NOTES
The string passed to fftdatar_write (first argument) gives the name used to store the data in the netcdf file The function varname_from_fname defined in the module m_hdr.F90 gives the mapping between the Abinit file extension and the netcdf name e.g. foo_VHXC.nc --> vxc This function is used in cut3d so that we can immediately select the data to analyze without having to prompt the user Remember to update varname_from_fname if you add a new file or if you change the name of the variable. fform i.e. the integer specification for data type is automatically initialized from varname.
SOURCE
674 subroutine fftdatar_write(varname,path,iomode,hdr,crystal,ngfft,cplex,nfft,nspden,datar,mpi_enreg,ebands) 675 676 !Arguments ------------------------------------ 677 !scalars 678 integer,intent(in) :: iomode,cplex,nfft,nspden 679 character(len=*),intent(in) :: varname,path 680 type(hdr_type),intent(inout) :: hdr 681 type(crystal_t),intent(in) :: crystal 682 type(ebands_t),optional,intent(in) :: ebands 683 type(MPI_type),intent(in) :: mpi_enreg 684 !arrays 685 integer,intent(in) :: ngfft(18) 686 real(dp),intent(inout) :: datar(cplex*nfft,nspden) 687 !type(pawrhoij_type),optional,intent(inout) :: pawrhoij_all(hdr%usepaw*crystal%natom) 688 689 !Local variables------------------------------- 690 !!scalars 691 integer,parameter :: master=0 692 integer :: n1,n2,n3,comm_fft,nproc_fft,me_fft,iarr,ierr,ii,ispden,unt,mpierr,fform 693 integer :: i3_glob,my_iomode 694 integer(kind=XMPI_OFFSET_KIND) :: hdr_offset,my_offset,nfft_tot 695 integer :: ncid,ncerr 696 character(len=fnlen) :: file_etsf 697 real(dp) :: cputime,walltime,gflops 698 character(len=500) :: msg,errmsg 699 type(abifile_t) :: abifile 700 !arrays 701 integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:),fftn3_distrib(:),ffti3_local(:) 702 integer(XMPI_OFFSET_KIND) :: bsize_frecord(nspden) 703 704 ! ************************************************************************* 705 706 abifile = abifile_from_varname(varname) 707 if (abifile%fform == 0) then 708 ABI_ERROR(sjoin("Cannot find any abifile object associated to varname:", varname)) 709 end if 710 ! Get fform from abifile. TODO: check file extension 711 fform = abifile%fform 712 713 comm_fft = mpi_enreg%comm_fft; nproc_fft = xmpi_comm_size(comm_fft); me_fft = mpi_enreg%me_fft 714 n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3); nfft_tot = n1*n2*n3 715 716 ! Select iomode 717 ! Use Fortran IO if nproc_fft 1, in principle this is not needed because the 718 ! MPI-IO code should produce binary files that are readable with Fortran-IO 719 ! but it seems that NAG uses its own binary format 720 my_iomode = iomode 721 if (my_iomode /= IO_MODE_ETSF .and. nproc_fft == 1) my_iomode = IO_MODE_FORTRAN 722 if (nproc_fft > 1 .and. my_iomode == IO_MODE_FORTRAN) my_iomode = IO_MODE_MPI 723 724 call wrtout(std_out, sjoin(ch10, "fftdatar_write: About to write data to:", path, "with iomode:",iomode2str(my_iomode))) 725 call cwtime(cputime, walltime, gflops, "start") 726 727 ! Get MPI-FFT tables from input ngfft 728 call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local) 729 730 select case (my_iomode) 731 case (IO_MODE_FORTRAN) 732 ABI_CHECK(nproc_fft == 1, "MPI-IO must be enabled when FFT parallelism is used") 733 if (open_file(path, msg, newunit=unt, form='unformatted', status='unknown', action="write") /= 0) then 734 ABI_ERROR(msg) 735 end if 736 call hdr%fort_write(unt, fform, ierr) 737 ABI_CHECK(ierr==0,"ierr !=0") 738 do ii=1,nspden 739 write(unt, err=10, iomsg=errmsg) (datar(iarr,ii), iarr=1,cplex * nfft) 740 end do 741 close(unt, err=10, iomsg=errmsg) 742 743 ! Write PAW rhoij 744 !call pawrhoij_io(hdr%pawrhoij,unit,hdr%nsppol,hdr%nspinor,hdr%nspden,hdr%lmn_size,hdr%typat,headform,"Write") 745 !call pawrhoij_io(rhoij_ptr,ncid,hdr%nsppol,hdr%nspinor,hdr%nspden,hdr%lmn_size,hdr%typat,& 746 ! HDR_LATEST_HEADFORM,"Write",form="netcdf") 747 748 #ifdef HAVE_MPI_IO 749 case (IO_MODE_MPI) 750 ! Find the first z-plane treated by this node. 751 ! WARNING: Here I assume that the z-planes in real space 752 ! are distributed in contiguous blocks (as usually done in MPI-FFT) 753 do i3_glob=1,n3 754 if (me_fft == fftn3_distrib(i3_glob)) exit 755 end do 756 ABI_CHECK(i3_glob /= n3 +1, "This processor does not have z-planes!") 757 758 ! Master writes the header. 759 if (me_fft == master) call hdr%write_to_fname(path, fform) 760 call xmpi_barrier(comm_fft) ! TODO: Non-blocking barrier. 761 762 call MPI_FILE_OPEN(comm_fft, path, MPI_MODE_RDWR, xmpio_info, unt, mpierr) 763 ABI_CHECK_MPI(mpierr,"MPI_FILE_OPEN") 764 765 ! Skip the header and get the offset of the header 766 call hdr_mpio_skip(unt,fform,hdr_offset) 767 !write(std_out,*)"i3_glob, nfft, hdr_offset,",i3_glob,nfft,hdr_offset,fftn3_distrib == me_fft 768 769 ! Each proc writes a contiguous slice of the nspden records. 770 ! my_offset is the position inside the Fortran record. 771 do ispden=1,nspden 772 my_offset = hdr_offset + xmpio_bsize_frm + ((ispden - 1) * 2 * xmpio_bsize_frm) + & 773 ((i3_glob-1) * cplex * n1 * n2 * xmpi_bsize_dp) + ((ispden-1) * cplex * nfft_tot * xmpi_bsize_dp) 774 call MPI_FILE_WRITE_AT_ALL(unt,my_offset,datar(:,ispden),cplex*nfft,MPI_DOUBLE_PRECISION,MPI_STATUS_IGNORE,mpierr) 775 ABI_CHECK_MPI(mpierr,"MPI_FILE_WRITE_AT_ALL") 776 end do 777 778 ! master writes the fortran record markers. 779 if (me_fft == master) then 780 bsize_frecord = cplex * nfft_tot * xmpi_bsize_dp 781 #if 1 782 my_offset = hdr_offset 783 do ispden=1,nspden 784 call xmpio_write_frm(unt,my_offset,xmpio_single,bsize_frecord(ispden),mpierr) 785 ABI_CHECK_MPI(mpierr,"xmpio_write_frm") 786 end do 787 #else 788 ! TODO: Understand why this code does not work! 789 call xmpio_write_frmarkers(unt,hdr_offset,xmpio_single,nspden,bsize_frecord,ierr) 790 ABI_CHECK(ierr==0, "xmpio_write_frmarkers") 791 #endif 792 end if 793 794 call MPI_FILE_CLOSE(unt,mpierr) 795 ABI_CHECK_MPI(mpierr,"FILE_CLOSE!") 796 797 ! Add full pawrhoij datastructure at the end of the file. 798 !if (present(pawrhoij_all) .and. me_fft == master .and. hdr%usepaw == 1) then 799 ! if (open_file(path, msg, newunit=unt, form='unformatted', status='old', action="write", access="append") /= 0) then 800 ! ABI_ERROR(msg) 801 ! end if 802 ! call pawrhoij_io(pawrhoij_all,un,hdr%nsppol,hdr%nspinor,hdr%nspden,hdr%lmn_size,hdr%typat,hdr%headform,"Write") 803 ! close(unt) 804 !end if 805 #endif 806 807 case (IO_MODE_ETSF) 808 file_etsf = nctk_ncify(path) 809 810 ! Write datar. 811 ncerr = nctk_write_datar(varname,file_etsf,ngfft,cplex,nfft,nspden, & 812 comm_fft,fftn3_distrib,ffti3_local,datar,action="create") 813 NCF_CHECK(ncerr) 814 call xmpi_barrier(comm_fft) 815 816 ! Master writes the header. 817 if (xmpi_comm_rank(comm_fft) == master) then 818 NCF_CHECK(nctk_open_modify(ncid, file_etsf, xmpi_comm_self)) 819 NCF_CHECK(hdr%ncwrite(ncid, fform, nc_define=.True.)) 820 ! Add information on the crystalline structure. 821 NCF_CHECK(crystal%ncwrite(ncid)) 822 if (present(ebands)) then 823 NCF_CHECK(ebands_ncwrite(ebands, ncid)) 824 end if 825 826 ! Add full pawrhoij datastructure. 827 !if (present(pawrhoij_all) .and. me_fft == master .and. hdr%usepaw == 1) then 828 ! call pawrhoij_io(pawrhoij_all,ncid,hdr%nsppol,hdr%nspinor,hdr%nspden,hdr%lmn_size,hdr%typat,hdr%headform,"Write", form="netcdf") 829 !end if 830 831 NCF_CHECK(nf90_close(ncid)) 832 end if 833 834 case default 835 ABI_ERROR(sjoin("Wrong iomode:",itoa(my_iomode))) 836 end select 837 838 call cwtime_report(" IO operation", cputime, walltime, gflops) 839 840 return 841 842 ! Handle Fortran IO error 843 10 continue 844 ABI_ERROR(errmsg) 845 846 end subroutine fftdatar_write
m_ioarr/fftdatar_write_from_hdr [ Functions ]
[ Top ] [ m_ioarr ] [ Functions ]
NAME
fftdatar_write_from_hdr
FUNCTION
Write an array in real space on the FFT box to file. crystal and ebands are constructed from the Abinit header.
TODO
This routine will be removed when crystal_t and ebands_t will become standard objects available in the GS/DFPT part.
INPUTS
[eigen](mband*hdr%nkpt*hdr%nsppol)=GS eigenvalues See fftdatar_write for the meaning of the other variables.
OUTPUT
SOURCE
871 subroutine fftdatar_write_from_hdr(varname,path,iomode,hdr,ngfft,cplex,nfft,nspden,datar,mpi_enreg,eigen) 872 873 !Arguments ------------------------------------ 874 !scalars 875 integer,intent(in) :: iomode,cplex,nfft,nspden 876 character(len=*),intent(in) :: varname,path 877 type(hdr_type),intent(inout) :: hdr 878 type(MPI_type),intent(in) :: mpi_enreg 879 !arrays 880 integer,intent(in) :: ngfft(18) 881 real(dp),intent(inout) :: datar(cplex*nfft,nspden) 882 real(dp),optional,intent(in) :: eigen(:) 883 884 !Local variables------------------------------- 885 !!scalars 886 integer :: mband 887 type(crystal_t) :: crystal 888 type(ebands_t) :: ebands 889 !arrays 890 real(dp),allocatable :: ene3d(:,:,:) 891 892 ! ************************************************************************* 893 894 crystal = hdr%get_crystal() 895 896 if (present(eigen)) then 897 mband = maxval(hdr%nband) 898 ABI_CHECK(size(eigen) == mband * hdr%nkpt * hdr%nsppol, "Wrong size(eigen)") 899 ABI_MALLOC(ene3d, (mband, hdr%nkpt, hdr%nsppol)) 900 call unpack_eneocc(hdr%nkpt, hdr%nsppol, mband, hdr%nband, eigen, ene3d) 901 ebands = ebands_from_hdr(hdr, mband, ene3d) 902 ABI_FREE(ene3d) 903 904 call fftdatar_write(varname,path,iomode,hdr,crystal,ngfft,cplex,nfft,nspden,datar,mpi_enreg,ebands=ebands) 905 call ebands_free(ebands) 906 else 907 call fftdatar_write(varname,path,iomode,hdr,crystal,ngfft,cplex,nfft,nspden,datar,mpi_enreg) 908 end if 909 910 call crystal%free() 911 912 end subroutine fftdatar_write_from_hdr
m_ioarr/fort_denpot_skip [ Functions ]
[ Top ] [ m_ioarr ] [ Functions ]
NAME
fort_denpot_skip
FUNCTION
Skip the header and the DEN/POT records. Mainly used to append data to a pre-existent file. Return exit code.
INPUTS
unit=Fortran unit number (already opened in the caller). msg=Error message if ierr /= 0
SOURCE
1253 integer function fort_denpot_skip(unit, msg) result(ierr) 1254 1255 !Arguments ------------------------------------ 1256 integer,intent(in) :: unit 1257 character(len=*),intent(out) :: msg 1258 1259 !Local variables------------------------------- 1260 integer :: ii,fform,nspden 1261 type(hdr_type) :: hdr 1262 1263 ! ********************************************************************* 1264 1265 ierr = 1 1266 call hdr_fort_read(hdr, unit, fform) 1267 if (fform == 0) then 1268 msg = "hdr_fort_read returned fform == 0"; return 1269 end if 1270 1271 nspden = hdr%nspden 1272 call hdr%free() 1273 1274 ! Skip the records with v1. 1275 do ii=1,nspden 1276 read(unit, iostat=ierr, iomsg=msg) 1277 if (ierr /= 0) return 1278 end do 1279 1280 ierr = 0 1281 1282 end function fort_denpot_skip
m_ioarr/ioarr [ Functions ]
[ Top ] [ m_ioarr ] [ Functions ]
NAME
ioarr
FUNCTION
Read or write rho(r) or v(r), either ground-state or response-functions. If ground-state, these arrays are real, if response-functions, these arrays are complex. (in general, an array stored in unformatted form on a real space fft grid). rdwr=1 to read, 2 to write This subroutine should be called only by one processor in the writing mode
INPUTS
(some may be output) accessfil= 0 for FORTRAN_IO 3 for ETSF_IO 4 for MPI_IO cplex=1 for real array, 2 for complex nfft=Number of FFT points treated by this node. ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft dtset <type(dataset_type)>=all input variables for this dataset fform=integer specification for data type: 2 for wf; 52 for density; 102 for potential old format (prior to ABINITv2.0): 1, 51 and 101. fildata=file name hdr <type(hdr_type)>=the header of wf, den and pot files if rdwr=1 , used to compare with the hdr of the read disk file if rdwr=2 , used as the header of the written disk file mpi_enreg=information about MPI parallelization rdwr=choice parameter, see above rdwrpaw=1 only if rhoij PAW quantities have to be read (if rdwr=1) [single_proc]=True if only ONE MPI process is calling this routine. This usually happens when master calls ioarr to read data that is then broadcasted in the caller. Default: False. Note that singleproc is not compatible with FFT parallelism because nfft is assumed to be the total number of points in the FFT mesh.
OUTPUT
(see side effects)
SIDE EFFECTS
Input/Output arr(cplex*nfft,nspden)=array on real space grid, returned for rdwr=1, input for rdwr=2 etotal=total energy (Ha), returned for rdwr=1 === if rdwrpaw/=0 === pawrhoij(my_natom*usepaw) <type(pawrhoij_type)>= paw rhoij occupancies and related data
SOURCE
128 subroutine ioarr(accessfil,arr,dtset,etotal,fform,fildata,hdr,mpi_enreg, & 129 & ngfft,cplex,nfft,pawrhoij,rdwr,rdwrpaw,wvl_den,single_proc) 130 131 !Arguments ------------------------------------ 132 !scalars 133 integer,intent(in) :: accessfil,cplex,nfft,rdwr,rdwrpaw 134 integer,intent(inout) :: fform 135 real(dp),intent(inout) :: etotal 136 character(len=*),intent(in) :: fildata 137 logical,optional,intent(in) :: single_proc 138 type(MPI_type),intent(inout) :: mpi_enreg 139 type(dataset_type),intent(in) :: dtset 140 type(hdr_type),intent(inout) :: hdr 141 type(wvl_denspot_type),optional, intent(in) :: wvl_den 142 !arrays 143 integer,intent(in) :: ngfft(18) 144 real(dp),intent(inout),target :: arr(cplex*nfft,dtset%nspden) 145 type(pawrhoij_type),intent(inout) :: pawrhoij(:) 146 147 !Local variables------------------------------- 148 integer :: ncid,ncerr 149 character(len=fnlen) :: file_etsf 150 #ifdef HAVE_BIGDFT 151 integer :: i,i1,i2,i3,ia,ind,n1,n2,n3 152 integer :: zindex,zstart,zstop 153 #endif 154 !scalars 155 integer,parameter :: master=0 156 logical,parameter :: ALLOW_FFTINTERP=.True. 157 logical :: need_fftinterp,icheck_fft,qeq0 158 integer :: in_unt,out_unt,nfftot_in,nfftot_out,nspden,ncplxfft 159 integer :: iomode,fform_dum,iarr,ierr,ispden,me,me_fft,comm_fft 160 integer :: comm_cell,usewvl,unt 161 integer :: restart,restartpaw,spaceComm,spaceComm_io 162 real(dp) :: cputime,walltime,gflops 163 character(len=500) :: msg,errmsg 164 character(len=fnlen) :: my_fildata 165 character(len=nctk_slen) :: varname 166 type(hdr_type),target :: hdr0 167 type(wffile_type) :: wff 168 type(MPI_type) :: MPI_enreg_seq 169 !arrays 170 integer :: ngfft_in(18),ngfft_out(18) 171 integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:),fftn3_distrib(:),ffti3_local(:) 172 real(dp), ABI_CONTIGUOUS pointer :: arr_file(:,:),my_density(:,:) 173 real(dp),allocatable :: rhor_file(:,:),rhog_in(:,:),rhor_out(:,:),rhog_out(:,:) 174 type(pawrhoij_type),pointer:: pawrhoij__(:) 175 176 ! ************************************************************************* 177 178 DBG_ENTER("COLL") 179 180 ncplxfft = cplex*nfft 181 182 restartpaw=0 183 my_fildata = fildata 184 nspden = dtset%nspden; usewvl = dtset%usewvl 185 186 ! Check validity of arguments--only rho(r) (51,52) and V(r) (101,102) are presently supported 187 if ( (fform-1)/2 /=25 .and. (fform-1)/2 /=50 ) then 188 write(msg,'(a,i0,a)')' Input fform= ',fform,' not allowed.' 189 ABI_BUG(msg) 190 end if 191 192 ! Print input fform 193 if ( (fform-1)/2==25 .and. rdwr==1) then 194 msg = ' ioarr: reading density data ' 195 else if ( (fform-1)/2==25 .and. rdwr==2) then 196 msg = ' ioarr: writing density data' 197 else if ( (fform-1)/2==50 .and. rdwr==1) then 198 msg = ' ioarr: reading potential data' 199 else if ( (fform-1)/2==50 .and. rdwr==2) then 200 msg = ' ioarr: writing potential data' 201 end if 202 call wrtout(std_out,msg) 203 204 call wrtout(std_out, 'ioarr: file name is: '//TRIM(fildata)) 205 206 if (accessfil == IO_MODE_ETSF) then ! Initialize filename in case of ETSF file. 207 file_etsf = nctk_ncify(fildata) 208 call wrtout(std_out,sjoin('file name for ETSF access: ', file_etsf)) 209 end if 210 211 !Some definitions for MPI-IO access 212 spaceComm = mpi_enreg%comm_cell 213 comm_cell = mpi_enreg%comm_cell 214 comm_fft = mpi_enreg%comm_fft 215 216 if (accessfil == 4) then 217 iomode=IO_MODE_MPI 218 if (rdwr==1) then 219 spaceComm=mpi_enreg%comm_cell 220 else 221 spaceComm=mpi_enreg%comm_fft 222 end if 223 me=xmpi_comm_rank(spaceComm) 224 if (mpi_enreg%nproc_fft>1) then 225 me_fft=mpi_enreg%me_fft 226 spaceComm_io=mpi_enreg%comm_fft 227 else 228 me_fft=0 229 spaceComm_io=xmpi_comm_self 230 end if 231 end if 232 if (usewvl==1) then 233 spaceComm=mpi_enreg%comm_cell 234 me=xmpi_comm_rank(spaceComm) 235 end if 236 237 ! Change communicators and ranks if we are calling ioarr with one single processor. 238 if (present(single_proc)) then 239 if (single_proc) then 240 spaceComm = xmpi_comm_self 241 spaceComm_io = xmpi_comm_self 242 ABI_CHECK(mpi_enreg%nproc_fft == 1, "single_proc cannot be used when nproc_fft > 1") 243 comm_cell = xmpi_comm_self 244 comm_fft = xmpi_comm_self 245 me = 0 246 end if 247 end if 248 249 !======================================= 250 !Handle input from disk file 251 !======================================= 252 253 call cwtime(cputime, walltime, gflops, "start") 254 255 if (rdwr==1) then 256 if (accessfil == 0 .or. accessfil == 4) then 257 258 ! Here master checks if the input rho(r) is given on a FFT mesh that quals 259 ! the one used in the run. If not, we perform a Fourier interpolation, we write the 260 ! interpolated rho(r) to a temporary file and we use this file to restart. 261 if (ALLOW_FFTINTERP .and. usewvl==0) then 262 need_fftinterp = .False.; icheck_fft = .True. 263 ! only master checks the FFT mesh if MPI-IO. All processors read ngfft if Fortran-IO 264 ! Note that, when Fortran-IO is used, we don't know if the routine is called 265 ! by a single processor or by all procs in comm_cell hence we cannot broadcast my_fildata 266 ! inside spaceComm as done if accessfil == 4 267 if (accessfil == 4) icheck_fft = (xmpi_comm_rank(spaceComm)==master) 268 269 if (icheck_fft) then 270 if (open_file(fildata,msg,newunit=in_unt,form='unformatted',status='old') /= 0) then 271 ABI_ERROR(msg) 272 end if 273 274 call hdr_io(fform_dum,hdr0,rdwr,in_unt) 275 need_fftinterp = (ANY(hdr%ngfft/=hdr0%ngfft) ) 276 qeq0=(hdr%qptn(1)**2+hdr%qptn(2)**2+hdr%qptn(3)**2<1.d-14) 277 ! FIXME: SHould handle double-grid if PAW 278 nfftot_in = product(hdr0%ngfft(1:3)) 279 nfftot_out = product(hdr%ngfft(1:3)) 280 281 if (need_fftinterp) then 282 write(msg, "(2a,2(a,3(i0,1x)))")& 283 "Will perform Fourier interpolation since in and out ngfft differ",ch10,& 284 "ngfft in file: ",hdr0%ngfft,", expected ngfft: ",hdr%ngfft 285 ABI_WARNING(msg) 286 287 ! Read rho(r) from file, interpolate it, write data and change fildata 288 ABI_MALLOC(rhor_file, (cplex*nfftot_in, hdr0%nspden)) 289 ABI_MALLOC(rhog_in, (2, nfftot_in)) 290 ABI_MALLOC(rhor_out, (cplex*nfftot_out, hdr0%nspden)) 291 ABI_MALLOC(rhog_out, (2, nfftot_out)) 292 293 do ispden=1,hdr0%nspden 294 read(in_unt, err=10, iomsg=errmsg) (rhor_file(iarr,ispden), iarr=1,cplex*nfftot_in) 295 end do 296 297 ngfft_in = dtset%ngfft; ngfft_out = dtset%ngfft 298 ngfft_in(1:3) = hdr0%ngfft(1:3); ngfft_out(1:3) = hdr%ngfft(1:3) 299 ngfft_in(4:6) = hdr0%ngfft(1:3); ngfft_out(4:6) = hdr%ngfft(1:3) 300 ngfft_in(9:18) = 0; ngfft_out(9:18) = 0 301 ngfft_in(10) = 1; ngfft_out(10) = 1 302 303 call initmpi_seq(MPI_enreg_seq) 304 ! Which one is coarse? Note that this part is not very robust and can fail! 305 if (ngfft_in(2) * ngfft_in(3) < ngfft_out(2) * ngfft_out(3)) then 306 call init_distribfft_seq(MPI_enreg_seq%distribfft,'c',ngfft_in(2),ngfft_in(3),'all') 307 call init_distribfft_seq(MPI_enreg_seq%distribfft,'f',ngfft_out(2),ngfft_out(3),'all') 308 else 309 call init_distribfft_seq(MPI_enreg_seq%distribfft,'f',ngfft_in(2),ngfft_in(3),'all') 310 call init_distribfft_seq(MPI_enreg_seq%distribfft,'c',ngfft_out(2),ngfft_out(3),'all') 311 end if 312 313 call fourier_interpol(cplex,hdr0%nspden,0,0,nfftot_in,ngfft_in,nfftot_out,ngfft_out,& 314 MPI_enreg_seq,rhor_file,rhor_out,rhog_in,rhog_out) 315 316 call destroy_mpi_enreg(MPI_enreg_seq) 317 318 ! MG Hack: Change fildata so that we will use this file to read the correct rho(r) 319 ! FIXME: This should be done in a cleaner way! 320 my_fildata = trim(fildata)//"__fftinterp_rhor__" 321 if (my_fildata == fildata) my_fildata = "__fftinterp_rhor__" 322 if (open_file(my_fildata,msg,newunit=out_unt,form='unformatted',status='unknown') /= 0) then 323 ABI_ERROR(msg) 324 end if 325 call hdr_io(fform_dum,hdr,2,out_unt) 326 do ispden=1,hdr0%nspden 327 write(out_unt, err=10, iomsg=errmsg) (rhor_out(iarr,ispden),iarr=1,cplex*nfftot_out) 328 end do 329 close(out_unt) 330 331 ABI_FREE(rhor_file) 332 ABI_FREE(rhog_in) 333 ABI_FREE(rhor_out) 334 ABI_FREE(rhog_out) 335 end if ! need_fftinterp 336 337 call hdr0%free() 338 close(in_unt, err=10, iomsg=errmsg) 339 end if ! master 340 if (accessfil == 4) call xmpi_bcast(my_fildata,master,spaceComm,ierr) 341 end if 342 343 if (accessfil == 4) then 344 unt = get_unit() 345 call WffOpen(iomode,spaceComm,my_fildata,ierr,wff,0,me,unt,spaceComm_io) 346 call hdr_io(fform_dum,hdr0,rdwr,wff) 347 ! Compare the internal header and the header from the file 348 call hdr_check(fform,fform_dum,hdr,hdr0,'COLL',restart,restartpaw) 349 350 else 351 if (open_file(my_fildata, msg, newunit=unt, form="unformatted", status="old", action="read") /= 0) then 352 ABI_ERROR(msg) 353 end if 354 ! Initialize hdr0, thanks to reading of unwff1 355 call hdr_io(fform_dum,hdr0,rdwr,unt) 356 ! Compare the internal header and the header from the file 357 call hdr_check(fform,fform_dum,hdr,hdr0,'COLL',restart,restartpaw) 358 end if 359 etotal=hdr0%etot 360 361 ! NOTE: should check that restart is possible !! 362 !call ptabs_fourdp(mpi_enreg,ngfft(2),ngfft(3),fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local) 363 364 ! If nspden[file] /= nspden, need a temporary array 365 if (hdr0%nspden/=nspden) then 366 ABI_MALLOC(arr_file,(cplex*nfft,hdr0%nspden)) 367 else 368 arr_file => arr 369 end if 370 371 ! Read data 372 do ispden=1,hdr0%nspden 373 if(accessfil == 4) then 374 call xderiveRRecInit(wff,ierr) 375 call xderiveRead(wff,arr(1:ncplxfft,ispden),ncplxfft,spaceComm_io,ierr) 376 call xderiveRRecEnd(wff,ierr) 377 378 !call xmpio_read_dp(mpi_fh,offset,sc_mode,ncount,buf,fmarker,mpierr,advance) 379 !do idat=1,ndat 380 ! do i3=1,n3 381 ! if( fftn3_distrib(i3) == me_fft) then 382 ! i3_local = ffti3_local(i3) 383 ! i3_ldat = i3_local + (idat - 1) * nd3proc 384 ! do i2=1,n2 385 ! frbase=n1*(i2-1+n2*(i3_local-1)) + (idat - 1) * nfft 386 ! do i1=1,n1 387 ! fofr(i1+frbase)=workr(1,i1,i2,i3_ldat) 388 ! end do 389 ! end do 390 ! end if 391 ! end do 392 !end do 393 394 else 395 read(unt, err=10, iomsg=errmsg) (arr_file(iarr,ispden),iarr=1,ncplxfft) 396 end if 397 end do 398 399 if (accessfil == 4) then 400 call wffclose(wff,ierr) 401 else 402 close (unit=unt, err=10, iomsg=errmsg) 403 end if 404 405 else if (accessfil == 3) then 406 407 ! Read the header and broadcast it in comm_cell 408 ! FIXME: Use xmpi_comm_self for the time-being because, in loper, ioarr 409 ! is called by me==0 410 call hdr_read_from_fname(hdr0, file_etsf, fform_dum, comm_cell) 411 !call hdr_read_from_fname(hdr0, file_etsf, fform_dum, xmpi_comm_self) 412 ABI_CHECK(fform_dum/=0, "hdr_read_from_fname returned fform 0") 413 414 ! Compare the internal header and the header from the file 415 call hdr_check(fform, fform_dum, hdr, hdr0, 'COLL', restart, restartpaw) 416 417 ! If nspden[file] /= nspden, need a temporary array 418 if (hdr0%nspden /= nspden) then 419 ABI_MALLOC(arr_file,(cplex*nfft,hdr0%nspden)) 420 else 421 arr_file => arr 422 end if 423 424 if (usewvl == 1) then 425 ! Read the array 426 if (fform==52) then ! density 427 varname = "density" 428 else if (fform==102) then ! all potential forms!!!! 429 varname = "exchange_correlation_potential" 430 end if 431 432 ! Open the file 433 NCF_CHECK(nctk_open_read(ncid, file_etsf, xmpi_comm_self)) 434 NCF_CHECK(nf90_get_var(ncid, nctk_idname(ncid, varname), arr_file)) 435 NCF_CHECK(nf90_close(ncid)) 436 else 437 ! Get MPI-FFT tables from input ngfft 438 call ptabs_fourdp(mpi_enreg,ngfft(2),ngfft(3),fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local) 439 440 ! Get the name of the netcdf variable from the ABINIT extension and read data. 441 varname = varname_from_fname(file_etsf) 442 ncerr = nctk_read_datar(file_etsf,varname,ngfft,cplex,nfft,hdr0%nspden,comm_fft,fftn3_distrib,ffti3_local,arr) 443 NCF_CHECK(ncerr) 444 end if 445 446 else 447 write(msg,'(a,i0,a)')'Bad value for accessfil', accessfil, ' on read ' 448 ABI_BUG(msg) 449 end if 450 451 call wrtout(std_out,sjoin("data read from disk file: ", fildata)) 452 453 etotal=hdr0%etot 454 455 ! Possibly need to convert the potential/density spin components 456 if (hdr0%nspden/=nspden) then 457 call denpot_spin_convert(arr_file,hdr0%nspden,arr,nspden,fform) 458 ABI_FREE(arr_file) 459 end if 460 461 ! Eventually copy (or distribute) PAW data 462 if (rdwrpaw==1.and.restartpaw/=0) then 463 pawrhoij__ => hdr0%pawrhoij ! Trick needed by nvhpc 23.9 464 if (size(pawrhoij__) /= size(pawrhoij)) then 465 call pawrhoij_copy(hdr0%pawrhoij,pawrhoij,comm_atom=mpi_enreg%comm_atom,mpi_atmtab=mpi_enreg%my_atmtab, & 466 keep_nspden=.true.) 467 else 468 call pawrhoij_copy(hdr0%pawrhoij,pawrhoij,keep_nspden=.true.) 469 end if 470 end if 471 472 if (accessfil == 0 .or. accessfil == 3 .or. accessfil == 4) call hdr0%free() 473 474 ! ======================================= 475 ! Set up for writing data 476 ! ======================================= 477 else if (rdwr==2) then 478 479 ! In the wavelet case (isolated boundary counditions), the 480 ! arr array has a buffer that we need to remove. 481 if (usewvl == 1) then 482 #ifdef HAVE_BIGDFT 483 zindex = wvl_den%denspot%dpbox%nscatterarr(me, 3) 484 if (wvl_den%denspot%rhod%geocode == 'F') then 485 n1 = (wvl_den%denspot%dpbox%ndims(1) - 31) / 2 486 n2 = (wvl_den%denspot%dpbox%ndims(2) - 31) / 2 487 n3 = (wvl_den%denspot%dpbox%ndims(3) - 31) / 2 488 zstart = max(15 - zindex, 0) 489 zstop = wvl_den%denspot%dpbox%nscatterarr(me, 2) + & 490 & wvl_den%denspot%dpbox%nscatterarr(me, 4) - & 491 & max(zindex + wvl_den%denspot%dpbox%nscatterarr(me, 2) & 492 & - 2 * n3 - 15, 0) 493 else 494 ABI_ERROR('ioarr: WVL not implemented yet.') 495 end if 496 if (zstop - zstart + 1 > 0) then 497 ! Our slab contains (zstop - zstart + 1) elements 498 ABI_MALLOC(my_density,((n1*2)*(n2*2)*(zstop-zstart),nspden)) 499 ! We copy the data except the buffer to my_density 500 ind = 0 501 502 do i3 = zstart, zstop - 1, 1 503 ia = (i3 - 1) * dtset%ngfft(1) * dtset%ngfft(2) 504 do i2 = 0, 2 * n2 - 1, 1 505 i = ia + (i2 + 14) * dtset%ngfft(1) + 14 506 do i1 = 0, 2 * n1 - 1, 1 507 i = i + 1 508 ind = ind + 1 509 my_density(ind, :) = arr(i, :) 510 end do 511 end do 512 end do 513 else 514 nullify(my_density) 515 end if 516 #else 517 BIGDFT_NOTENABLED_ERROR() 518 if(.false. .and. present(wvl_den))then 519 write(std_out,*)' One should not be here' 520 endif 521 #endif 522 end if 523 524 ! Make sure ngfft agrees with hdr%ngfft. 525 if (usewvl == 0) then 526 if (any(ngfft(:3) /= hdr%ngfft(:3))) then 527 write(msg,"(2(a,3(1x,i0)))")"input ngfft: ",ngfft(:3),"differs from hdr%ngfft: ",hdr%ngfft(:3) 528 ABI_ERROR(msg) 529 end if 530 end if 531 532 if (accessfil == 0 .or. accessfil == 4) then 533 if(accessfil == 4) then 534 unt = get_unit() 535 call WffOpen(iomode,spaceComm,fildata,ierr,wff,0,me,unt) 536 call hdr_io(fform,hdr,rdwr,wff) 537 else 538 if (open_file(fildata, msg, newunit=unt, form='unformatted', status='unknown', action="write") /= 0) then 539 ABI_ERROR(msg) 540 end if 541 542 ! Write header 543 call hdr_io(fform,hdr,rdwr,unt) 544 end if 545 546 ! Write actual data 547 do ispden=1,nspden 548 if(accessfil == 4) then 549 call xderiveWRecInit(wff,ierr,me_fft) 550 call xderiveWrite(wff,arr(1:ncplxfft,ispden),ncplxfft,spaceComm_io,ierr) 551 call xderiveWRecEnd(wff,ierr,me_fft) 552 else 553 if (usewvl == 0) then 554 write(unt, err=10, iomsg=errmsg) (arr(iarr,ispden),iarr=1,ncplxfft) 555 else 556 write(unt, err=10, iomsg=errmsg) (my_density(iarr,ispden),iarr=1,size(my_density, 1)) 557 end if 558 end if 559 end do 560 561 if(accessfil == 4) then 562 call WffClose(wff,ierr) 563 else 564 close(unt, err=10, iomsg=errmsg) 565 end if 566 567 else if ( accessfil == 3 ) then 568 569 ! Master in comm_fft creates the file and writes the header. 570 if (xmpi_comm_rank(comm_fft) == 0) then 571 call hdr%write_to_fname(file_etsf, fform) 572 end if 573 call xmpi_barrier(comm_fft) 574 575 ! Write the array 576 if (usewvl == 0) then 577 ! Get MPI-FFT tables from input ngfft 578 call ptabs_fourdp(mpi_enreg,ngfft(2),ngfft(3),fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local) 579 580 varname = varname_from_fname(file_etsf) 581 ncerr = nctk_write_datar(varname,file_etsf,ngfft,cplex,nfft,nspden,comm_fft,fftn3_distrib,ffti3_local,arr) 582 NCF_CHECK(ncerr) 583 else 584 NCF_CHECK(nctk_open_modify(ncid, file_etsf, xmpi_comm_self)) 585 586 if (fform==52) then ! density 587 varname = "density" 588 if (usewvl == 0) then 589 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, varname), arr)) 590 else 591 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, varname), my_density)) 592 end if 593 else if (fform==102) then ! all potential forms!!!! 594 varname = "exchange_correlation_potential" 595 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, varname), arr)) 596 end if 597 598 NCF_CHECK(nf90_close(ncid)) 599 end if 600 601 else 602 write(msg,'(a,i0,a)')'Bad value for accessfil', accessfil, ' on write ' 603 ABI_ERROR(msg) 604 end if 605 606 if (usewvl == 1 .and. associated(my_density)) then 607 ABI_FREE(my_density) 608 end if 609 610 call wrtout(std_out,sjoin(' Data written to disk file:', fildata)) 611 612 else 613 write(msg,'(a,i0,a)')'Called with rdwr = ',rdwr,' not allowed.' 614 ABI_BUG(msg) 615 end if 616 617 call cwtime_report(" IO operation", cputime, walltime, gflops) 618 619 DBG_EXIT("COLL") 620 621 return 622 623 ! Handle Fortran IO error 624 10 continue 625 ABI_ERROR(errmsg) 626 627 end subroutine ioarr
m_ioarr/read_rhor [ Functions ]
[ Top ] [ m_ioarr ] [ Functions ]
NAME
read_rhor
FUNCTION
Read the DEN file with name fname reporting the density on the real FFT mesh specified through the input variable ngfft. If the FFT mesh asked in input and that found on file differ, the routine performs a FFT interpolation and renormalize the density so that it integrates to the correct number of electrons. The interpolation is done only for NC. For PAW, this is not possible because one should include the onsite contribution so this task is delegated to the caller.
INPUTS
fname=Name of the file cplex=1 if array is real, 2 if complex e.g. DFPT density. nspden=Number of spin density components. nfft=Number of FFT points (treated by this processor) ngfft(18)=Info on the FFT mesh. pawread= 1 if pawrhoij should be read from file, 0 otherwise. Meaningful only if usepaw==1. mpi_enreg<MPI_type>=Information about MPI parallelization comm=MPI communicator. See notes [check_hdr] <type(hdr_type)>=Optional. Used to compare with the hdr read from disk file The routine will abort if restart cannot be performed. [allow_interp]=If True, the density read from file will be interpolated if the mesh differs from the one expected by the caller. This option is usually used in **self-consistent** calculations. If False (default), the code stops if the two meshes are different.
OUTPUT
orhor(cplex*nfft,nspden)=The density on the real space mesh. ohdr=Abinit header read from file. pawrhoij(my_natom*usepaw) <type(pawrhoij_type)>= paw rhoij occupancies and related data. only if pawread==1. The arrays is supposed to be already allocated in the caller and its size must be consistent with the MPI communicator comm.
NOTES
if xmpi_comm_size(comm) == 1, nfft shall be equal to nfftot, and len(pawrhoij) == natom This means that one can call this routine with if (xmpi_comm_rank(comm) == 0) call read_rhor(...., comm=xmpi_comm_self) to get the full array and pawrhoij(natom) on the master node. if xmpi_comm_size(comm) > 1, nfft represents the number of FFT points treated by this processor, and pawrhoij is dimensioned with my_natom All the processors inside comm and comm_atom should call this routine.
SOURCE
965 subroutine read_rhor(fname, cplex, nspden, nfft, ngfft, pawread, mpi_enreg, orhor, ohdr, pawrhoij, comm, & 966 check_hdr, allow_interp) ! Optional 967 968 !Arguments ------------------------------------ 969 !scalars 970 integer,intent(in) :: cplex,nfft,nspden,pawread,comm 971 character(len=*),intent(in) :: fname 972 type(MPI_type),intent(in) :: mpi_enreg 973 type(hdr_type),intent(out) :: ohdr 974 type(hdr_type),optional,intent(in) :: check_hdr 975 logical,optional,intent(in) :: allow_interp 976 !arrays 977 integer,intent(in) :: ngfft(18) 978 real(dp),intent(out) :: orhor(cplex*nfft,nspden) 979 type(pawrhoij_type),intent(inout) :: pawrhoij(:) 980 981 !Local variables------------------------------- 982 !scalars 983 integer,parameter :: master=0 984 integer :: unt,fform,iomode,my_rank,mybase,globase,cplex_file 985 integer :: ispden,ifft,nfftot_file,nprocs,ierr,i1,i2,i3,i3_local,n1,n2,n3 986 integer,parameter :: fform_den=52 987 integer :: restart, restartpaw 988 integer :: ncerr 989 real(dp) :: ratio,ucvol 990 real(dp) :: cputime,walltime,gflops 991 logical :: need_interp,have_mpifft,allow_interp__ 992 character(len=500) :: msg,errmsg 993 character(len=fnlen) :: my_fname 994 character(len=nctk_slen) :: varname 995 !arrays 996 integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:),fftn3_distrib(:),ffti3_local(:) 997 real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3),tsec(2) 998 real(dp),allocatable :: rhor_file(:,:),rhor_tmp(:,:) 999 type(pawrhoij_type),allocatable :: pawrhoij_file(:) 1000 1001 ! ************************************************************************* 1002 1003 my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm) 1004 n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3); have_mpifft = (nfft /= product(ngfft(1:3))) 1005 allow_interp__ = .False.; if (present(allow_interp)) allow_interp__ = allow_interp 1006 1007 call timab(1280,1,tsec) 1008 call wrtout(std_out, sjoin(" About to read data(r) from:", fname), do_flush=.True.) 1009 call cwtime(cputime, walltime, gflops, "start") 1010 1011 ! Master node opens the file, read the header and the FFT data 1012 ! This approach facilitates the interpolation of the density if in_ngfft(1:3) /= file_ngfft(1:3) 1013 if (my_rank == master) then 1014 my_fname = fname 1015 if (nctk_try_fort_or_ncfile(my_fname, msg) /= 0 ) then 1016 ABI_ERROR(msg) 1017 end if 1018 1019 iomode = iomode_from_fname(my_fname) 1020 select case (iomode) 1021 1022 case (IO_MODE_FORTRAN, IO_MODE_MPI) 1023 if (open_file(my_fname, msg, newunit=unt, form='unformatted', status='old', action="read") /= 0) then 1024 ABI_ERROR(msg) 1025 end if 1026 1027 call hdr_fort_read(ohdr, unt, fform) 1028 1029 ! Check important dimensions. 1030 ABI_CHECK(fform /= 0, sjoin("fform == 0 while reading:", my_fname)) 1031 !if (fform /= fform_den) then 1032 ! write(msg, "(3a, 2(a, i0))")' File: ',trim(my_fname),ch10,' is not a density file. fform: ',fform,", expecting: ", fform_den 1033 ! ABI_WARNING(msg) 1034 !end if 1035 cplex_file = 1 1036 if (ohdr%pertcase /= 0) then 1037 cplex_file = 2; if (ohdr%qptn(1)**2 + ohdr%qptn(2)**2 + ohdr%qptn(3)**2 <1.d-14) cplex_file= 1 1038 end if 1039 ABI_CHECK(cplex_file == cplex, "cplex_file != cplex") 1040 1041 ! Read FFT array (full box) 1042 nfftot_file = product(ohdr%ngfft(:3)) 1043 ABI_MALLOC(rhor_file, (cplex*nfftot_file, ohdr%nspden)) 1044 do ispden=1,ohdr%nspden 1045 read(unt, err=10, iomsg=errmsg) (rhor_file(ifft,ispden), ifft=1,cplex*nfftot_file) 1046 end do 1047 close(unt) 1048 1049 case (IO_MODE_ETSF) 1050 NCF_CHECK(nctk_open_read(unt, my_fname, xmpi_comm_self)) 1051 call hdr_ncread(ohdr, unt, fform) 1052 1053 ! Check important dimensions. 1054 ABI_CHECK(fform /= 0, sjoin("fform == 0 while reading:", my_fname)) 1055 !if (fform /= fform_den) then 1056 ! write(msg, "(2a, 2(a, i0))")' File: ',trim(my_fname),' is not a density file: fform= ',fform,", expecting:", fform_den 1057 ! ABI_WARNING(msg) 1058 !end if 1059 1060 cplex_file = 1 1061 if (ohdr%pertcase /= 0) then 1062 cplex_file = 2; if (ohdr%qptn(1)**2 + ohdr%qptn(2)**2 + ohdr%qptn(3)**2 <1.d-14) cplex_file= 1 1063 end if 1064 ABI_CHECK(cplex_file == cplex, "cplex_file != cplex") 1065 1066 ! Read FFT array (full box) 1067 nfftot_file = product(ohdr%ngfft(:3)) 1068 ABI_MALLOC(rhor_file, (cplex*nfftot_file, ohdr%nspden)) 1069 1070 varname = varname_from_fname(my_fname) 1071 ncerr= nf90_get_var(unt, nctk_idname(unt, varname), rhor_file, & 1072 count=[cplex, ohdr%ngfft(1), ohdr%ngfft(2), ohdr%ngfft(3), ohdr%nspden]) 1073 NCF_CHECK(ncerr) 1074 NCF_CHECK(nf90_close(unt)) 1075 1076 case default 1077 ABI_ERROR(sjoin("Wrong iomode:", itoa(iomode))) 1078 end select 1079 1080 need_interp = any(ohdr%ngfft(1:3) /= ngfft(1:3)) 1081 if (need_interp) then 1082 msg = sjoin("Different FFT meshes. Caller expects:", ltoa(ngfft(1:3)), & 1083 ". File: ", ltoa(ohdr%ngfft(1:3)), ". Need to perform interpolation.") 1084 ABI_COMMENT(msg) 1085 if (.not. allow_interp__) then 1086 write(msg, "(5a)") & 1087 " Cannot continue as allow_interp = .False. ", ch10, & 1088 " Please set ngfft to: ", trim(ltoa(ohdr%ngfft(1:3))), " in the input file" 1089 ABI_ERROR(msg) 1090 end if 1091 1092 ABI_MALLOC(rhor_tmp, (cplex*product(ngfft(1:3)), ohdr%nspden)) 1093 call timab(1281,1,tsec) 1094 call interpolate_denpot(cplex, ohdr%ngfft(1:3), ohdr%nspden, rhor_file, ngfft(1:3), rhor_tmp) 1095 call timab(1281,2,tsec) 1096 1097 ohdr%ngfft(1:3) = ngfft(1:3) 1098 nfftot_file = product(ohdr%ngfft(:3)) 1099 ABI_FREE(rhor_file) 1100 ABI_MALLOC(rhor_file, (cplex*nfftot_file, ohdr%nspden)) 1101 rhor_file = rhor_tmp 1102 ABI_FREE(rhor_tmp) 1103 1104 ! Renormalize charge to avoid errors due to the interpolation. 1105 ! Do this only for NC since for PAW we should add the onsite contribution. 1106 ! This is left to the caller. 1107 !if (ohdr%usepaw == 0) then 1108 if (ohdr%usepaw == 0 .and. fform == fform_den) then 1109 call metric(gmet, gprimd, -1, rmet, ohdr%rprimd, ucvol) 1110 ratio = ohdr%nelect / (sum(rhor_file(:,1))*ucvol/ product(ngfft(1:3))) 1111 rhor_file = rhor_file * ratio 1112 write(msg,'(a,f8.2,a,f8.4)')' Expected nelect: ',ohdr%nelect,' renormalization ratio: ',ratio 1113 call wrtout(std_out,msg) 1114 end if 1115 end if ! need_interp 1116 1117 ! Read PAW Rhoij 1118 if (ohdr%usepaw == 1) then 1119 ABI_MALLOC(pawrhoij_file, (ohdr%natom)) 1120 call pawrhoij_nullify(pawrhoij_file) 1121 call pawrhoij_alloc(pawrhoij_file, ohdr%pawrhoij(1)%cplex_rhoij, ohdr%pawrhoij(1)%nspden, ohdr%pawrhoij(1)%nspinor, & 1122 ohdr%pawrhoij(1)%nsppol, ohdr%typat, lmnsize=ohdr%lmn_size, qphase=ohdr%pawrhoij(1)%qphase) 1123 call pawrhoij_copy(ohdr%pawrhoij, pawrhoij_file) 1124 end if 1125 1126 ! Check that restart is possible ! 1127 ! This check must be done here because we may have changed hdr% if need_interp 1128 if (present(check_hdr)) then 1129 ! FIXME: Temporary hack: fform_den to make hdr_check happy! 1130 call hdr_check(fform_den, fform_den, check_hdr, ohdr, "COLL", restart, restartpaw) 1131 !call hdr_check(fform_den, fform, check_hdr, ohdr, "COLL", restart, restartpaw) 1132 end if 1133 1134 end if ! master 1135 1136 if (nprocs == 1) then 1137 if (ohdr%nspden == nspden) then 1138 orhor = rhor_file 1139 else 1140 call denpot_spin_convert(rhor_file,ohdr%nspden,orhor,nspden,fform) 1141 end if 1142 if (pawread == 1) call pawrhoij_copy(pawrhoij_file, pawrhoij, keep_nspden=.true.) 1143 1144 else 1145 call ohdr%bcast(master, my_rank, comm) 1146 call xmpi_bcast(fform, master, comm, ierr) 1147 1148 ! Eventually copy (or distribute) PAW data 1149 if (ohdr%usepaw == 1 .and. pawread == 1) then 1150 if (my_rank /= master) then 1151 ABI_MALLOC(pawrhoij_file, (ohdr%natom)) 1152 call pawrhoij_nullify(pawrhoij_file) 1153 call pawrhoij_alloc(pawrhoij_file, ohdr%pawrhoij(1)%cplex_rhoij, ohdr%pawrhoij(1)%nspden, ohdr%pawrhoij(1)%nspinor, & 1154 ohdr%pawrhoij(1)%nsppol, ohdr%typat, lmnsize=ohdr%lmn_size, qphase=ohdr%pawrhoij(1)%qphase) 1155 end if 1156 if (size(ohdr%pawrhoij) /= size(pawrhoij)) then 1157 call pawrhoij_copy(ohdr%pawrhoij,pawrhoij,comm_atom=mpi_enreg%comm_atom,mpi_atmtab=mpi_enreg%my_atmtab, & 1158 keep_nspden=.true.) 1159 else 1160 call pawrhoij_copy(ohdr%pawrhoij,pawrhoij, keep_nspden=.true.) 1161 end if 1162 end if 1163 1164 if (my_rank /= master) then 1165 nfftot_file = product(ohdr%ngfft(1:3)) 1166 ABI_MALLOC(rhor_file, (cplex*nfftot_file, ohdr%nspden)) 1167 end if 1168 call xmpi_bcast(rhor_file, master, comm,ierr) 1169 1170 if (have_mpifft) then 1171 ! Extract slice treated by this MPI-FFT process. 1172 call ptabs_fourdp(mpi_enreg, ngfft(2), ngfft(3), fftn2_distrib, ffti2_local, fftn3_distrib, ffti3_local) 1173 if (ohdr%nspden==nspden) then 1174 do ispden=1,nspden 1175 do i3=1,n3 1176 if (fftn3_distrib(i3) /= mpi_enreg%me_fft) cycle 1177 i3_local = ffti3_local(i3) 1178 do i2=1,n2 1179 mybase = cplex * (n1 * (i2-1 + n2*(i3_local-1))) 1180 globase = cplex * (n1 * (i2-1 + n2*(i3-1))) 1181 do i1=1,n1*cplex 1182 orhor(i1+mybase,ispden) = rhor_file(i1+globase,ispden) 1183 end do 1184 end do 1185 end do 1186 end do 1187 else 1188 do i3=1,n3 1189 if (fftn3_distrib(i3) /= mpi_enreg%me_fft) cycle 1190 i3_local = ffti3_local(i3) 1191 do i2=1,n2 1192 mybase = 1 + cplex * (n1 * (i2-1 + n2*(i3_local-1))) 1193 globase = 1 + cplex * (n1 * (i2-1 + n2*(i3-1))) 1194 call denpot_spin_convert(rhor_file,ohdr%nspden,orhor,nspden,fform,& 1195 istart_in=globase,istart_out=mybase,nelem=n1*cplex) 1196 end do 1197 end do 1198 end if 1199 else 1200 if (ohdr%nspden==nspden) then 1201 orhor = rhor_file 1202 else 1203 call denpot_spin_convert(rhor_file,ohdr%nspden,orhor,nspden,fform) 1204 end if 1205 end if 1206 end if ! nprocs > 1 1207 1208 ABI_FREE(rhor_file) 1209 1210 if (allocated(pawrhoij_file)) then 1211 call pawrhoij_free(pawrhoij_file) 1212 ABI_FREE(pawrhoij_file) 1213 end if 1214 1215 ! Non-collinear magnetism: avoid zero magnetization, because it produces numerical instabilities 1216 ! Add a small real to the magnetization 1217 if (nspden==4) orhor(:,4)=orhor(:,4)+tol14 1218 if (ohdr%usepaw==1.and.size(pawrhoij)>0) then 1219 if (pawrhoij(1)%nspden==4) then 1220 do i1=1,size(pawrhoij) 1221 pawrhoij(i1)%rhoijp(:,4)=pawrhoij(i1)%rhoijp(:,4)+tol10 1222 end do 1223 end if 1224 end if 1225 1226 call timab(1280,2,tsec) 1227 call cwtime_report(" read_rhor", cputime, walltime, gflops) 1228 return 1229 1230 ! Handle Fortran IO error 1231 10 continue 1232 ABI_ERROR(errmsg) 1233 1234 end subroutine read_rhor