TABLE OF CONTENTS


m_mkrho/atomden [ Functions ]

[ Top ] [ m_mkrho ] [ Functions ]

NAME

 atomden

FUNCTION

 Construct atomic proto-bulk density (i.e. the superposed density
 from neutral, isolated atoms at the bulk atomic positions).
 This is useful if one wants to construct the bonding density:

 rho^{bnd} = rho^{bulk}(r)
                 - \sum_{\alpha}\rho^{atm}_{\alpha}(r-R_{\alpha})

 Where rho^{bulk} is the bulk density, rho^{atm} the atomic density
 and the index \alpha sums over all atoms. the R_{\alpha} are the
 atomic positions in the bulk. This routine calculates the sum over
 rho^{atm}_{\alpha}(r-R_{\alpha}) on a grid.

 Units are atomic.

INPUTS

 calctype : type of calculation
          'replace' zero the input/output density array
          'add'     add to the input/output density array
 natom : number of atoms in cell
 ntypat : number of different types of atoms in cell
 typat(natom) : type of each atom
 ngrid : number of gridpoints
 r_vec_grid(3,ngrid) : real (non-reduced) coordinates for grid points
 rho(ngrid) : input/output density array
 a(3),b(3),c(3) : real-space basis vectors
 atom_pos(3,natom) : reduced coordinates for atomic positions
 natomgr(ntypat) : number of gridpoints for each atomic density grid
 natomgrmax : max(natomgr(ntypat))
 atomrgrid(natomgrmax,ntypat)
 density(natomgrmax,ntypat)

OUTPUT

 rho(ngrid) : input/output density array

SIDE EFFECTS

NOTES

 There are two ways to compile the proto density in real space
 for a solid. One alternative is that the density is calculated
 for an extended grid encompassing the sphere of points around
 one atom, and the results are folded back into the unit cell.
 On the other hand one can, around each grid point, identify the
 number of atoms in a sphere equivalent to the length of the radial
 grid for each type of atom.
 The second approach, with some modification, is taken here. The
 numer of atoms in a supercell cell are listed such that the supercell
 encompasses the atoms which could contribute to any point in the grid.
 That list is kept and cycled through, to avoid recalculating it at
 each point.
 Note that the density calculated from the atom is the spherical
 average, since there is no preferred direction without any
 external field (and it's simpler)

SOURCE

2253 subroutine atomden(MPI_enreg,natom,ntypat,typat,ngrid,r_vec_grid,rho,a,b,c,atom_pos, &
2254 &                  natomgr,natomgrmax,atomrgrid,density,prtvol,calctype)
2255 
2256 !Arguments ------------------------------------
2257 !scalars
2258  integer,intent(in) :: natom,ntypat,ngrid,natomgrmax,prtvol
2259  character(len=7),intent(in) :: calctype
2260 !arrays
2261  type(MPI_type),intent(in) :: MPI_enreg
2262  integer,intent(in) :: typat(natom),natomgr(ntypat)
2263  real(dp),intent(in) :: r_vec_grid(3,ngrid),a(3),b(3),c(3)
2264  real(dp),intent(in) :: atom_pos(3,natom),atomrgrid(natomgrmax,ntypat)
2265  real(dp),intent(in) :: density(natomgrmax,ntypat)
2266  real(dp),intent(inout) :: rho(ngrid)
2267 
2268 !Local variables-------------------------------
2269 !scalars
2270  character(len=500) :: message
2271  integer :: cnt,delta,i,l,m,n,iatom,itypat,igrid,ncells,n_grid_p
2272  integer :: ierr,spaceComm,nprocs,master,rank,remainder
2273  real(dp) :: a_norm,b_norm,c_norm
2274  real(dp) :: r_max,R_sphere_max,dp_dummy,ybcbeg,ybcend
2275 !arrays
2276  integer :: n_equiv_atoms(ntypat),grid_index(ngrid)
2277  integer :: my_start_equiv_atoms(ntypat)
2278  integer :: my_end_equiv_atoms(ntypat)
2279  integer :: l_min(ntypat),m_min(ntypat),n_min(ntypat)
2280  integer :: l_max(ntypat),m_max(ntypat),n_max(ntypat)
2281  real(dp) :: center(3),dp_vec_dummy(3),delta_a(3),delta_b(3),delta_c(3)
2282  real(dp) :: r_atom(3),grid_distances(ngrid)
2283  integer, allocatable :: new_index(:),i_1d_dummy(:)
2284  real(dp),allocatable :: equiv_atom_dist(:,:),equiv_atom_pos(:,:,:),rho_temp(:,:)
2285  real(dp),allocatable :: dp_1d_dummy(:),dp_2d_dummy(:,:),ypp(:)
2286  real(dp),allocatable :: x_fit(:),y_fit(:)
2287 
2288 
2289 ! ************************************************************************
2290 
2291 !initialise and check parallel execution
2292  spaceComm=MPI_enreg%comm_cell
2293  nprocs=xmpi_comm_size(spaceComm)
2294  rank=MPI_enreg%me_kpt
2295 
2296  master=0
2297 
2298 !initialise variables and vectors
2299  a_norm = sqrt(dot_product(a,a))
2300  b_norm = sqrt(dot_product(b,b))
2301  c_norm = sqrt(dot_product(c,c))
2302  center = (a+b+c)*half
2303  dp_dummy = dot_product(a,b)/(b_norm*b_norm)
2304  dp_vec_dummy = dp_dummy*b
2305  delta_a = a - dp_vec_dummy
2306  dp_dummy = dot_product(b,a)/(a_norm*a_norm)
2307  dp_vec_dummy = dp_dummy*a
2308  delta_b = b - dp_vec_dummy
2309  dp_dummy = dot_product(c,(a+b))/(dot_product((a+b),(a+b)))
2310  dp_vec_dummy = dp_dummy*(a+b)
2311  delta_c = c - dp_vec_dummy
2312  ABI_MALLOC(rho_temp,(ngrid,ntypat))
2313  rho_temp = zero
2314 
2315 !write(std_out,*) '*** --- In atomden --- ***'
2316 !write(std_out,*) ' a_norm:',a_norm,' b_norm:',b_norm,' c_norm:',c_norm
2317 !write(std_out,*) 'delta_a:',delta_a,'delta_b:',delta_b,'delta_c:',delta_c
2318 !write(std_out,*) ' center:',center
2319 
2320 !Find supercell which will contain all possible contributions
2321 !for all atoms, and enumerate positions for all atoms
2322 !TODO list of atoms can be "pruned", i.e identify all atoms
2323 !that can't possibly contribute and remove from list.
2324 !Should be most important for very oblique cells
2325  do itypat=1,ntypat
2326    R_sphere_max = atomrgrid(natomgr(itypat),itypat)
2327    l_min(itypat) = -ceiling(R_sphere_max/sqrt(dot_product(delta_a,delta_a)))
2328    l_max(itypat) = -l_min(itypat)
2329    m_min(itypat) = -ceiling(R_sphere_max/sqrt(dot_product(delta_b,delta_b)))
2330    m_max(itypat) = -m_min(itypat)
2331    n_min(itypat) = -ceiling(R_sphere_max/sqrt(dot_product(delta_c,delta_c)))
2332    n_max(itypat) = -n_min(itypat)
2333    ncells = (l_max(itypat)-l_min(itypat)+1) &
2334 &   *(m_max(itypat)-m_min(itypat)+1) &
2335 &   *(n_max(itypat)-n_min(itypat)+1)
2336    n_equiv_atoms(itypat) = 0
2337    do iatom=1,natom
2338      if (typat(iatom)==itypat) then
2339        n_equiv_atoms(itypat) = n_equiv_atoms(itypat) + ncells
2340      end if ! if type=itypat
2341    end do ! number of atoms per cell
2342    if ((rank==master).and.(prtvol>9)) then
2343      write(message,'(a)') '*** --- In atomden --- find box ***'
2344      call wrtout(std_out,message,'COLL')
2345      write(message,'(a,I4)') ' itypat:',itypat
2346      call wrtout(std_out,message,'COLL')
2347      write(message,'(2(a,I4))') ' l_min:',l_min(itypat),' l_max:',l_max(itypat)
2348      call wrtout(std_out,message,'COLL')
2349      write(message,'(2(a,I4))') ' m_min:',m_min(itypat),' m_max:',m_max(itypat)
2350      call wrtout(std_out,message,'COLL')
2351      write(message,'(2(a,I4))') ' n_min:',n_min(itypat),' n_max:',n_max(itypat)
2352      call wrtout(std_out,message,'COLL')
2353      write(message,'(2(a,I4))') ' n_equiv_atoms:',n_equiv_atoms(itypat)
2354      call wrtout(std_out,message,'COLL')
2355    end if
2356  end do !atom type
2357 
2358 !allocate arrays
2359  n = maxval(n_equiv_atoms)
2360  ABI_MALLOC(equiv_atom_pos,(3,n,ntypat))
2361  ABI_MALLOC(equiv_atom_dist,(n,ntypat))
2362  equiv_atom_pos = zero
2363  equiv_atom_dist = zero
2364 
2365 !Find positions and distance of atoms from center of cell
2366  do itypat=1,ntypat
2367    i = 1
2368    do l=l_min(itypat),l_max(itypat)
2369      do m=m_min(itypat),m_max(itypat)
2370        do n=n_min(itypat),n_max(itypat)
2371          do iatom=1,natom
2372            if (typat(iatom)==itypat) then
2373              if (i>n_equiv_atoms(itypat)) then
2374                ABI_ERROR('atomden: i>n_equiv_atoms')
2375              end if
2376              equiv_atom_pos(:,i,itypat) = (atom_pos(1,iatom)+dble(l))*a &
2377 &             + (atom_pos(2,iatom)+dble(m))*b &
2378 &             + (atom_pos(3,iatom)+dble(n))*c
2379              dp_vec_dummy = equiv_atom_pos(:,i,itypat)-center
2380              equiv_atom_dist(i,itypat) = &
2381 &             sqrt(dot_product(dp_vec_dummy,dp_vec_dummy))
2382              i = i + 1
2383            end if
2384          end do
2385        end do !n
2386      end do !m
2387    end do !l
2388 !  write(std_out,*) '*** --- In atomden --- find equiv ***'
2389 !  write(std_out,*) ' itypat:',itypat
2390 !  write(std_out,*) ' equiv_atom_pos:'
2391 !  write(std_out,*) equiv_atom_pos(:,:,itypat)
2392 !  write(std_out,*) ' equiv_atom_dist:',equiv_atom_dist(:,itypat)
2393  end do !atom type
2394 
2395 !Sort the atoms after distance so that the density from the ones
2396 !furthest away can be added first. This is to prevent truncation error.
2397  do itypat=1,ntypat
2398    n = n_equiv_atoms(itypat)
2399    ABI_MALLOC(dp_1d_dummy,(n))
2400    ABI_MALLOC(new_index,(n))
2401    ABI_MALLOC(dp_2d_dummy,(3,n))
2402    dp_1d_dummy = equiv_atom_dist(1:n,itypat)
2403    dp_2d_dummy = equiv_atom_pos(1:3,1:n,itypat)
2404    do i=1,n
2405      new_index(i) = i
2406    end do
2407    call sort_dp(n,dp_1d_dummy,new_index,tol14)
2408    do i=1,n
2409      !write(std_out,*) i,' -> ',new_index(i)
2410      equiv_atom_pos(1:3,n+1-i,itypat) = dp_2d_dummy(1:3,new_index(i))
2411      equiv_atom_dist(1:n,itypat) = dp_1d_dummy
2412    end do
2413    ABI_FREE(dp_1d_dummy)
2414    ABI_FREE(new_index)
2415    ABI_FREE(dp_2d_dummy)
2416 !  write(std_out,*) '*** --- In atomden ---  sorting atoms ***'
2417 !  write(std_out,*) ' itypat:',itypat
2418 !  write(std_out,*) ' equiv_atom_pos:'
2419 !  write(std_out,*) equiv_atom_pos(:,:,itypat)
2420 !  write(std_out,*) ' equiv_atom_dist:',equiv_atom_dist(:,itypat)
2421  end do ! atom type
2422 
2423 !Divide the work in case of parallel execution
2424  if (nprocs==1) then ! Make sure everything runs with one proc
2425    if (prtvol>9) then
2426      write(message,'(a)') '  In atomden - number of processors:     1'
2427      call wrtout(std_out,message,'COLL')
2428      write(message,'(a)') '  Calculation of proto-atomic density done in serial'
2429      call wrtout(std_out,message,'COLL')
2430    end if
2431    do itypat=1,ntypat
2432      if (prtvol>9) then
2433        write(message,'(a,I6)') '  Number of equivalent atoms:',n_equiv_atoms(itypat)
2434        call wrtout(std_out,message,'COLL')
2435      end if
2436      my_start_equiv_atoms(itypat) = 1
2437      my_end_equiv_atoms(itypat) = n_equiv_atoms(itypat)
2438    end do
2439  else
2440    if (rank==master.and.prtvol>9) then
2441      write(message,'(a,I5)') '  In atomden - number of processors:',nprocs
2442      call wrtout(std_out,message,'COLL')
2443      write(message,'(a)') '  Calculation of proto-atomic density done in parallel'
2444      call wrtout(std_out,message,'COLL')
2445    end if
2446    do itypat=1,ntypat
2447      if (rank==master.and.prtvol>9) then
2448        write(message,'(a,I6)') '  Number of equivalent atoms:',n_equiv_atoms(itypat)
2449        call wrtout(std_out,message,'COLL')
2450      end if
2451 !    Divide the atoms among the processors by shuffling indices
2452      delta = int(floor(real(n_equiv_atoms(itypat))/real(nprocs)))
2453      remainder = n_equiv_atoms(itypat)-nprocs*delta
2454      my_start_equiv_atoms(itypat) = 1+rank*delta
2455      my_end_equiv_atoms(itypat) = (rank+1)*delta
2456 !    Divide the remainder points among the processors
2457 !    by shuffling indices
2458      if ((rank+1)>remainder) then
2459        my_start_equiv_atoms(itypat) = my_start_equiv_atoms(itypat) + remainder
2460        my_end_equiv_atoms(itypat) = my_end_equiv_atoms(itypat) + remainder
2461      else
2462        my_start_equiv_atoms(itypat) = my_start_equiv_atoms(itypat) + rank
2463        my_end_equiv_atoms(itypat) = my_end_equiv_atoms(itypat) + rank + 1
2464      end if
2465      if (prtvol>9) then
2466        write(message,'(a,I3)') '          For atom type: ',itypat
2467        call wrtout(std_out,message,'PERS')
2468 !      write(message,'(a,I6)') '  I''ll take atoms from: ',my_start_equiv_atoms(itypat)
2469 !      call wrtout(std_out,message,'PERS')
2470 !      write(message,'(a,I6)') '           total for me: ',my_end_equiv_atoms(itypat)
2471 !      call wrtout(std_out,message,'PERS')
2472        write(message,'(a,I6)') '            total for me: ', &
2473 &       my_end_equiv_atoms(itypat)+1-my_start_equiv_atoms(itypat)
2474        call wrtout(std_out,message,'PERS')
2475      end if
2476    end do
2477  end if
2478 
2479 !Loop over types of atoms and equivalent atoms and
2480 !interpolate density onto grid
2481  do itypat=1,ntypat
2482 !  do iatom=my_start_equiv_atoms(itypat),my_end_equiv_atoms(itypat)
2483 
2484    cnt = 0
2485    iatom = rank+1 - nprocs
2486 !  Parallel execution of loop
2487    do
2488      cnt = cnt + 1
2489      iatom = iatom + nprocs
2490      if (iatom>n_equiv_atoms(itypat)) exit ! Exit if index is too large
2491 
2492      if (mod(cnt,100)==0.and.prtvol>0) then
2493        write(message,'(2(a,I6))') ' atoms so far',cnt,' of: ',n_equiv_atoms(itypat)/nprocs
2494        call wrtout(std_out,message,'PERS')
2495      end if
2496 
2497      r_max = atomrgrid(natomgr(itypat),itypat)
2498      r_atom = equiv_atom_pos(:,iatom,itypat)
2499 
2500 !    Set up an array with the gridpoint distances
2501      i = 1
2502      grid_distances = zero
2503      grid_index = 0
2504      do igrid=1,ngrid
2505        dp_vec_dummy(:) = r_vec_grid(:,igrid) - r_atom(:)
2506        dp_dummy = sqrt(dot_product(dp_vec_dummy,dp_vec_dummy))
2507        if (dp_dummy <= r_max) then
2508          grid_distances(i) = dp_dummy
2509          grid_index(i) = igrid
2510          i = i + 1
2511        else
2512          cycle ! cycle if point is too far away
2513        end if
2514      end do
2515      n_grid_p = i - 1
2516 
2517      if (n_grid_p==0) cycle ! Cycle if no point needs
2518 !    to be interpolated
2519 
2520 !    Sort points to be interpolated in ascending order
2521      ABI_MALLOC(dp_1d_dummy,(n_grid_p))
2522      ABI_MALLOC(new_index,(n_grid_p))
2523      ABI_MALLOC(i_1d_dummy,(n_grid_p))
2524      dp_1d_dummy = grid_distances(1:n_grid_p)
2525      do i=1,n_grid_p
2526        new_index(i) = i
2527      end do
2528      call sort_dp(n_grid_p,dp_1d_dummy,new_index,tol16)
2529      grid_distances(1:n_grid_p) = dp_1d_dummy
2530      i_1d_dummy = grid_index(1:n_grid_p)
2531      do i=1,n_grid_p
2532        !write(std_out,*) i_1d_dummy(i),' -> ',i_1d_dummy(new_index(i))
2533        grid_index(i) = i_1d_dummy(new_index(i))
2534      end do
2535      ABI_FREE(dp_1d_dummy)
2536      ABI_FREE(new_index)
2537      ABI_FREE(i_1d_dummy)
2538 
2539 !    Interpolate density onto all grid points
2540      ABI_MALLOC(ypp,(natomgr(itypat)))
2541      ABI_MALLOC(x_fit,(n_grid_p))
2542      ABI_MALLOC(y_fit,(n_grid_p))
2543      ypp = zero; y_fit = zero
2544      ybcbeg = zero; ybcend = zero
2545      x_fit = grid_distances(1:n_grid_p)
2546      call spline(atomrgrid(1:natomgr(itypat),itypat), &
2547 &     density(1:natomgr(itypat),itypat), &
2548 &     natomgr(itypat),ybcbeg,ybcend,ypp)
2549      call splint(natomgr(itypat),atomrgrid(1:natomgr(itypat),itypat), &
2550 &     density(1:natomgr(itypat),itypat),ypp,n_grid_p, &
2551 &     x_fit,y_fit)
2552 
2553 !    Save the interpolated points to grid
2554      do i=1,n_grid_p
2555        rho_temp(grid_index(i),itypat) = rho_temp(grid_index(i),itypat) + y_fit(i)
2556      end do
2557      ABI_FREE(ypp)
2558      ABI_FREE(x_fit)
2559      ABI_FREE(y_fit)
2560 
2561    end do ! n equiv atoms
2562  end do ! type of atom
2563 
2564  ! Collect all contributions to rho_temp if we are running in parallel
2565  if (nprocs>1) then
2566    call xmpi_barrier(spaceComm)
2567    call xmpi_sum_master(rho_temp,master,spaceComm,ierr)
2568    call xmpi_barrier(spaceComm)
2569    if (prtvol>9) then
2570      write(message,'(a)') '  In atomden - contributions to rho_temp collected'
2571      call wrtout(std_out,message,'PERS')
2572    end if
2573  end if
2574 
2575 !Now rho_temp contains the atomic protodensity for each atom.
2576 !Check whether this is to replace or be added to the input/output array
2577 !and sum up contributions
2578  if (trim(calctype)=='replace') rho = zero
2579  do itypat=1,ntypat
2580    rho(:) = rho(:) + rho_temp(:,itypat)
2581  end do
2582 
2583  ! deallocations
2584  ABI_SFREE(rho_temp)
2585  ABI_SFREE(equiv_atom_pos)
2586  ABI_SFREE(equiv_atom_dist)
2587 
2588  end subroutine atomden

m_mkrho/initro [ Functions ]

[ Top ] [ m_mkrho ] [ Functions ]

NAME

 initro

FUNCTION

 Initialize the density using either:
  - a gaussian of adjustable decay length (norm-conserving psp)
  - PS atomic valence density from psp file (PAW or NC psps with valence change in the pp file)

INPUTS

 atindx(natom)=index table for atoms (see gstate.f)
 densty(ntypat,4)=parameters for initialisation of the density of each atom type
 gmet(3,3)=reciprocal space metric (Bohr**-2)
 gsqcut=cutoff G**2 for included G s in fft box (larger sphere).
 izero=if 1, unbalanced components of rho(g) have to be set to zero
 mgfft=maximum size of 1D FFTs
 mpi_enreg=information about mpi parallelization
 mqgrid=number of grid pts in q array for n^AT(q) spline.
 natom=number of atoms in cell.
 nattyp(ntypat)=number of atoms of each type in cell.
 nfft=(effective) number of FFT grid points (for this processor)
 ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
 ntypat=number of types of atoms in cell.
 nspden=number of spin-density components
 psps<type(pseudopotential_type)>=variables related to pseudopotentials
 pawtab(ntypat*usepaw) <type(pawtab_type)>=paw tabulated starting data
 ph1d(2,3*(2*mgfft+1)*natom)=1-dim phase information for given atom coordinates.
 qgrid(mqgrid)=q grid for spline atomic valence density n^AT(q) from 0 to qmax.
 spinat(3,natom)=initial spin of each atom, in unit of hbar/2.
 ucvol=unit cell volume (Bohr**3).
 usepaw= 0 for non paw calculation; =1 for paw calculation
 zion(ntypat)=charge on each type of atom (real number)
 znucl(ntypat)=atomic number, for each type of atom

OUTPUT

 rhog(2,nfft)=initialized total density in reciprocal space
 rhor(nfft,nspden)=initialized total density in real space.
         as well as spin-up part if spin-polarized

SOURCE

1004 subroutine initro(atindx,densty,gmet,gsqcut,izero,mgfft,mpi_enreg,mqgrid,natom,nattyp,&
1005 &  nfft,ngfft,nspden,ntypat,psps,pawtab,ph1d,qgrid,rhog,rhor,spinat,ucvol,usepaw,zion,znucl)
1006 
1007 !Arguments ------------------------------------
1008 !scalars
1009  integer,intent(in) :: izero,mgfft,mqgrid,natom,nfft,nspden,ntypat
1010  integer,intent(in) :: usepaw
1011  real(dp),intent(in) :: gsqcut,ucvol
1012  type(mpi_type),intent(in) :: mpi_enreg
1013  type(pseudopotential_type),intent(in) :: psps
1014 !arrays
1015  integer,intent(in) :: atindx(natom),nattyp(ntypat),ngfft(18)
1016  real(dp),intent(in) :: densty(ntypat,4),gmet(3,3),ph1d(2,3*(2*mgfft+1)*natom)
1017  real(dp),intent(in) :: qgrid(mqgrid),spinat(3,natom),zion(ntypat)
1018  real(dp),intent(in) :: znucl(ntypat)
1019  real(dp),intent(out) :: rhog(2,nfft),rhor(nfft,nspden)
1020  type(pawtab_type),intent(in) :: pawtab(ntypat*usepaw)
1021 
1022 !Local variables-------------------------------
1023 !scalars
1024  integer,parameter :: im=2,re=1
1025  integer :: i1,i2,i3,ia,ia1,ia2,id1,id2,id3,ig1,ig2,ig3,ii,ispden
1026  integer :: itypat,jj,jtemp,me_fft,n1,n2,n3,nproc_fft
1027  real(dp),parameter :: tolfix=1.000000001_dp
1028  real(dp) :: aa,alf2pi2,bb,cc,cutoff,dd,diff,dq,dq2div6,dqm1,fact,fact0,gmag
1029  real(dp) :: gsquar,rhoat,sfi,sfr
1030  real(dp) :: xnorm
1031  character(len=500) :: message
1032 !arrays
1033  integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:),fftn3_distrib(:),ffti3_local(:)
1034  real(dp) :: length(ntypat)
1035  real(dp),allocatable :: work(:), spinat_indx(:,:)
1036  logical :: use_gaussian(ntypat)
1037 
1038 ! *************************************************************************
1039 
1040  if (nspden==4) then
1041    ABI_COMMENT('initro: might work yet for nspden=4 (not checked)')
1042    !write(std_out,*)' spinat',spinat(1:3,1:natom)
1043  end if
1044 
1045  n1=ngfft(1); n2=ngfft(2); n3=ngfft(3); me_fft=ngfft(11); nproc_fft=ngfft(10)
1046 
1047  ABI_MALLOC(work,(nfft))
1048  ABI_MALLOC(spinat_indx,(3,natom))
1049 
1050  ! Get the distrib associated with this fft_grid
1051  call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
1052 
1053  ! Transfer the spinat array to an array in which the atoms have the proper order, type by type.
1054  do ia=1,natom
1055    spinat_indx(:,atindx(ia))=spinat(:,ia)
1056  end do
1057 
1058  ! Check whether the values of spinat are acceptable
1059  if (nspden==2)then
1060    ia1=1
1061    do itypat=1,ntypat
1062      !ia1,ia2 sets range of loop over atoms:
1063      ia2=ia1+nattyp(itypat)-1
1064      do ia=ia1,ia2
1065        if( sqrt(spinat_indx(1,ia)**2+spinat_indx(2,ia)**2+spinat_indx(3,ia)**2) &
1066            > abs(zion(itypat))*(1.0_dp + epsilon(0.0_dp)) ) then
1067          write(message, '(a,i0,a,a,3es11.4,a,a,a,es11.4)' )&
1068          '  For type-ordered atom number ',ia,ch10,&
1069          '  input spinat=',spinat_indx(:,ia),'  is larger, in magnitude,',ch10,&
1070          '  than zion(ia)=',zion(itypat)
1071          call wrtout([std_out, ab_out], message)
1072        end if
1073      end do
1074      ia1=ia2+1
1075    end do
1076  end if
1077 
1078  ! Compute the decay length of each type of atom depending on data available in pseudos.
1079  jtemp=0
1080  do itypat=1,ntypat
1081    use_gaussian(itypat)=.true.
1082    if (usepaw==0) use_gaussian(itypat) = .not. psps%nctab(itypat)%has_tvale
1083    if (usepaw==1) use_gaussian(itypat)=(pawtab(itypat)%has_tvale==0)
1084    if (.not.use_gaussian(itypat)) jtemp=jtemp+1
1085 
1086    if (use_gaussian(itypat)) then
1087      length(itypat) = atom_length(densty(itypat,1),zion(itypat),znucl(itypat))
1088      write(message,'(a,i3,a,f12.4,a,a,a,f12.4,a,i3,a,es12.4,a)' )&
1089       ' initro: for itypat=',itypat,', take decay length=',length(itypat),',',ch10,&
1090       ' initro: indeed, coreel=',znucl(itypat)-zion(itypat),', nval=',int(zion(itypat)),' and densty=',densty(itypat,1),'.'
1091      call wrtout(std_out,message)
1092    else
1093      write(message,"(a,i3,a)")' initro: for itypat=',itypat,", take pseudo charge density from pp file"
1094      call wrtout(std_out,message)
1095    end if
1096  end do
1097 
1098  if (jtemp>0) then
1099    dq=(qgrid(mqgrid)-qgrid(1))/dble(mqgrid-1)
1100    dqm1=1.0_dp/dq
1101    dq2div6=dq**2/6.0_dp
1102  end if
1103 
1104  cutoff=gsqcut*tolfix
1105  xnorm=1.0_dp/ucvol
1106 
1107  id1=n1/2+2
1108  id2=n2/2+2
1109  id3=n3/2+2
1110 
1111  if(nspden /= 4) then
1112 
1113    do ispden=nspden,1,-1
1114      ! This loop overs spins will actually be as follows:
1115      !  ispden=2 for spin up
1116      !  ispden=1 for total spin (also valid for non-spin-polarized calculations)
1117      !
1118      ! The reverse ispden order is chosen, in order to end up with
1119      ! rhog containing the proper total density.
1120      rhog = zero
1121 
1122      ia1=1
1123      do itypat=1,ntypat
1124        if (use_gaussian(itypat)) alf2pi2=(two_pi*length(itypat))**2
1125 
1126        ! ia1,ia2 sets range of loop over atoms:
1127        ia2=ia1+nattyp(itypat)-1
1128        ii=0
1129        jtemp=0
1130 
1131        do i3=1,n3
1132          ig3=i3-(i3/id3)*n3-1
1133          do i2=1,n2
1134            ig2=i2-(i2/id2)*n2-1
1135            if (fftn2_distrib(i2)==me_fft) then
1136              do i1=1,n1
1137 
1138                ig1=i1-(i1/id1)*n1-1
1139                ii=ii+1
1140                gsquar=dble(ig1*ig1)*gmet(1,1)+dble(ig2*ig2)*gmet(2,2)+&
1141                       dble(ig3*ig3)*gmet(3,3)+dble(2*ig1*ig2)*gmet(1,2)+&
1142                       dble(2*ig2*ig3)*gmet(2,3)+dble(2*ig3*ig1)*gmet(3,1)
1143 
1144                ! Skip G**2 outside cutoff:
1145                if (gsquar<=cutoff) then
1146 
1147                  ! Assemble structure factor over all atoms of given type,
1148                  ! also taking into account the spin-charge on each atom:
1149 
1150                  sfr=zero;sfi=zero
1151                  if (ispden==1) then
1152                    do ia=ia1,ia2
1153                      sfr=sfr+phre_ini(ig1,ig2,ig3,ia)
1154                      sfi=sfi-phimag_ini(ig1,ig2,ig3,ia)
1155                    end do
1156                    if (use_gaussian(itypat)) then
1157                      sfr=sfr*zion(itypat)
1158                      sfi=sfi*zion(itypat)
1159                    end if
1160                  else
1161                    fact0=half;if (.not.use_gaussian(itypat)) fact0=half/zion(itypat)
1162                    do ia=ia1,ia2
1163                      ! Here, take care only of the z component
1164                      fact=fact0*(zion(itypat)+spinat_indx(3,ia))
1165                      sfr=sfr+phre_ini(ig1,ig2,ig3,ia)*fact
1166                      sfi=sfi-phimag_ini(ig1,ig2,ig3,ia)*fact
1167                    end do
1168                  end if
1169 
1170                  ! Charge density integrating to one
1171                  if (use_gaussian(itypat)) then
1172                    rhoat=xnorm*exp(-gsquar*alf2pi2)
1173                    ! Multiply structure factor times rhoat (atomic density in reciprocal space)
1174                    rhog(re,ii)=rhog(re,ii)+sfr*rhoat
1175                    rhog(im,ii)=rhog(im,ii)+sfi*rhoat
1176                  else
1177                    gmag=sqrt(gsquar)
1178                    jj=1+int(gmag*dqm1)
1179                    diff=gmag-qgrid(jj)
1180                    bb = diff*dqm1
1181                    aa = one-bb
1182                    cc = aa*(aa**2-one)*dq2div6
1183                    dd = bb*(bb**2-one)*dq2div6
1184                    if (usepaw == 1) then
1185                      rhoat=(aa*pawtab(itypat)%tvalespl(jj,1)+bb*pawtab(itypat)%tvalespl(jj+1,1)+&
1186 &                     cc*pawtab(itypat)%tvalespl(jj,2)+dd*pawtab(itypat)%tvalespl(jj+1,2)) *xnorm
1187                    else if (usepaw == 0) then
1188                      rhoat=(aa*psps%nctab(itypat)%tvalespl(jj,1)+bb*psps%nctab(itypat)%tvalespl(jj+1,1)+&
1189                      cc*psps%nctab(itypat)%tvalespl(jj,2)+dd*psps%nctab(itypat)%tvalespl(jj+1,2))*xnorm
1190                    else
1191                      ABI_BUG('Initialization of density is non consistent.')
1192                    end if
1193                    ! Multiply structure factor times rhoat (atomic density in reciprocal space)
1194                    rhog(re,ii)=rhog(re,ii)+sfr*rhoat
1195                    rhog(im,ii)=rhog(im,ii)+sfi*rhoat
1196                  end if
1197 
1198                else
1199                  jtemp=jtemp+1
1200                end if
1201 
1202              end do ! i1
1203            end if
1204          end do ! i2
1205        end do ! i3
1206        ia1=ia2+1
1207 
1208      end do ! itypat
1209 
1210      ! Set contribution of unbalanced components to zero
1211      if (izero==1) then
1212        call zerosym(rhog,2,n1,n2,n3,comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
1213      end if
1214      !write(std_out,*)"initro: ispden, ucvol * rhog(:2,1)",ispden, ucvol * rhog(:2,1)
1215 
1216      ! Note, we end with ispden=1, so that rhog contains the total density
1217      call fourdp(1,rhog,work,1,mpi_enreg,nfft,1,ngfft,0)
1218      rhor(:,ispden)=work(:)
1219    end do ! End loop on spins
1220 
1221  else if (nspden==4) then
1222 
1223    do ispden=nspden,1,-1
1224      ! This loop overs spins will actually be as follows:
1225      ! ispden=2,3,4 for mx,my,mz
1226      ! ispden=1 for total spin (also valid for non-spin-polarized calculations)
1227      ! The reverse ispden order is chosen, in order to end up with
1228      ! rhog containing the proper total density.
1229 
1230      rhog(:,:)=zero
1231 
1232      ia1=1
1233      do itypat=1,ntypat
1234 
1235        if (use_gaussian(itypat)) alf2pi2=(two_pi*length(itypat))**2
1236 
1237        ! ia1,ia2 sets range of loop over atoms:
1238        ia2=ia1+nattyp(itypat)-1
1239        ii=0
1240        jtemp=0
1241        do i3=1,n3
1242          ig3=i3-(i3/id3)*n3-1
1243          do i2=1,n2
1244            ig2=i2-(i2/id2)*n2-1
1245            if (fftn2_distrib(i2)==me_fft) then
1246              do i1=1,n1
1247 
1248                ig1=i1-(i1/id1)*n1-1
1249                ii=ii+1
1250                gsquar=dble(ig1*ig1)*gmet(1,1)+dble(ig2*ig2)*gmet(2,2)+&
1251                       dble(ig3*ig3)*gmet(3,3)+dble(2*ig1*ig2)*gmet(1,2)+&
1252                       dble(2*ig2*ig3)*gmet(2,3)+dble(2*ig3*ig1)*gmet(3,1)
1253 
1254                ! Skip G**2 outside cutoff:
1255                if (gsquar<=cutoff) then
1256 
1257                  ! Assemble structure factor over all atoms of given type,
1258                  ! also taking into account the spin-charge on each atom:
1259                  sfr=zero;sfi=zero
1260                  if(ispden==1)then
1261                    do ia=ia1,ia2
1262                      sfr=sfr+phre_ini(ig1,ig2,ig3,ia)
1263                      sfi=sfi-phimag_ini(ig1,ig2,ig3,ia)
1264                    end do
1265                    if (use_gaussian(itypat)) then
1266                      sfr=sfr*zion(itypat)
1267                      sfi=sfi*zion(itypat)
1268                    end if
1269                  else
1270                    fact0=one;if (.not.use_gaussian(itypat)) fact0=one/zion(itypat)
1271                    do ia=ia1,ia2
1272                      ! Here, take care of the components of m
1273                      fact=fact0*spinat_indx(ispden-1,ia)
1274                      sfr=sfr+phre_ini(ig1,ig2,ig3,ia)*fact
1275                      sfi=sfi-phimag_ini(ig1,ig2,ig3,ia)*fact
1276                    end do
1277                  end if
1278 
1279                  ! Charge density integrating to one
1280                  if (use_gaussian(itypat)) then
1281                    rhoat=xnorm*exp(-gsquar*alf2pi2)
1282                  else
1283                    gmag=sqrt(gsquar)
1284                    jj=1+int(gmag*dqm1)
1285                    diff=gmag-qgrid(jj)
1286                    bb = diff*dqm1
1287                    aa = one-bb
1288                    cc = aa*(aa**2-one)*dq2div6
1289                    dd = bb*(bb**2-one)*dq2div6
1290                    if (usepaw == 1) then
1291                      rhoat=(aa*pawtab(itypat)%tvalespl(jj,1)+bb*pawtab(itypat)%tvalespl(jj+1,1)+&
1292 &                     cc*pawtab(itypat)%tvalespl(jj,2)+dd*pawtab(itypat)%tvalespl(jj+1,2)) *xnorm
1293                    else if (usepaw == 0) then
1294                      rhoat=(aa*psps%nctab(itypat)%tvalespl(jj,1)+bb*psps%nctab(itypat)%tvalespl(jj+1,1)+&
1295                      cc*psps%nctab(itypat)%tvalespl(jj,2)+dd*psps%nctab(itypat)%tvalespl(jj+1,2))*xnorm
1296                    else
1297                      ABI_BUG('Initialization of density is non consistent.')
1298                    end if
1299                  end if
1300 
1301                  ! Multiply structure factor times rhoat (atomic density in reciprocal space)
1302                  rhog(re,ii)=rhog(re,ii)+sfr*rhoat
1303                  rhog(im,ii)=rhog(im,ii)+sfi*rhoat
1304                else
1305                  jtemp=jtemp+1
1306                end if
1307 
1308              end do ! i1
1309            end if
1310          end do ! i2
1311        end do ! i3
1312        ia1=ia2+1
1313      end do ! itypat
1314 
1315      ! Set contribution of unbalanced components to zero
1316      if (izero==1) then
1317        call zerosym(rhog,2,n1,n2,n3,comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
1318      end if
1319      !write(std_out,*)"initro: ispden, ucvol * rhog(:2,1)",ispden, ucvol * rhog(:2,1)
1320 
1321      ! Note, we end with ispden=1, so that rhog contains the total density
1322      call fourdp(1,rhog,work,1,mpi_enreg,nfft,1,ngfft,0)
1323      rhor(:,ispden)=work(:)
1324    end do ! ispden
1325 
1326    ! Non-collinear magnetism: avoid zero magnetization, because it produces numerical instabilities
1327    ! Add a small real to the magnetization
1328    if (all(abs(spinat(:,:))<tol10)) rhor(:,4)=rhor(:,4)+tol14
1329 
1330  end if ! nspden==4
1331 
1332  ABI_FREE(spinat_indx)
1333  ABI_FREE(work)
1334 
1335  contains
1336 
1337 !Real and imaginary parts of phase.
1338    function phr_ini(x1,y1,x2,y2,x3,y3)
1339 
1340    real(dp) :: phr_ini
1341    real(dp),intent(in) :: x1,x2,x3,y1,y2,y3
1342    phr_ini=(x1*x2-y1*y2)*x3-(y1*x2+x1*y2)*y3
1343  end function phr_ini
1344 
1345    function phi_ini(x1,y1,x2,y2,x3,y3)
1346 
1347    real(dp) :: phi_ini
1348    real(dp),intent(in) :: x1,x2,x3,y1,y2,y3
1349    phi_ini=(x1*x2-y1*y2)*y3+(y1*x2+x1*y2)*x3
1350  end function phi_ini
1351 
1352    function ph1_ini(nri,ig1,ia)
1353 
1354    real(dp) :: ph1_ini
1355    integer,intent(in) :: nri,ig1,ia
1356    ph1_ini=ph1d(nri,ig1+1+n1+(ia-1)*(2*n1+1))
1357  end function ph1_ini
1358 
1359    function ph2_ini(nri,ig2,ia)
1360 
1361    real(dp) :: ph2_ini
1362    integer,intent(in) :: nri,ig2,ia
1363    ph2_ini=ph1d(nri,ig2+1+n2+(ia-1)*(2*n2+1)+natom*(2*n1+1))
1364  end function ph2_ini
1365 
1366    function ph3_ini(nri,ig3,ia)
1367 
1368    real(dp) :: ph3_ini
1369    integer,intent(in) :: nri,ig3,ia
1370    ph3_ini=ph1d(nri,ig3+1+n3+(ia-1)*(2*n3+1)+natom*(2*n1+1+2*n2+1))
1371  end function ph3_ini
1372 
1373    function phre_ini(ig1,ig2,ig3,ia)
1374 
1375    real(dp) :: phre_ini
1376    integer,intent(in) :: ig1,ig2,ig3,ia
1377    phre_ini=phr_ini(ph1_ini(re,ig1,ia),ph1_ini(im,ig1,ia),&
1378 &   ph2_ini(re,ig2,ia),ph2_ini(im,ig2,ia),ph3_ini(re,ig3,ia),ph3_ini(im,ig3,ia))
1379  end function phre_ini
1380 
1381    function phimag_ini(ig1,ig2,ig3,ia)
1382 
1383    real(dp) :: phimag_ini
1384    integer,intent(in) :: ig1,ig2,ig3,ia
1385    phimag_ini=phi_ini(ph1_ini(re,ig1,ia),ph1_ini(im,ig1,ia),&
1386 &   ph2_ini(re,ig2,ia),ph2_ini(im,ig2,ia),ph3_ini(re,ig3,ia),ph3_ini(im,ig3,ia))
1387  end function phimag_ini
1388 
1389 end subroutine initro

m_mkrho/m_mkrho [ Modules ]

[ Top ] [ Modules ]

NAME

  m_mkrho

FUNCTION

  Procedures for computing densities from KS orbitals.

COPYRIGHT

  Copyright (C) 1998-2024 ABINIT group (DCA, XG, GMR, LSI, AR, MB, MT, SM, VR, FJ)
  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_mkrho
23 
24  use, intrinsic :: iso_fortran_env, only: int32, int64, real32, real64
25 
26  use defs_basis
27  use defs_wvltypes
28  use m_abicore
29  use m_xmpi
30  use m_errors
31  use m_dtset
32  use m_extfpmd
33 
34  use defs_abitypes,  only : MPI_type
35  use m_fstrings,     only : sjoin, itoa
36  use m_time,         only : timab
37  use m_fftcore,      only : sphereboundary
38  use m_fft,          only : fftpac, zerosym, fourwf, fourdp
39  use m_bandfft_kpt,  only : bandfft_kpt_set_ikpt
40  use m_paw_dmft,     only : paw_dmft_type
41  use m_spacepar,     only : symrhg
42  use defs_datatypes, only : pseudopotential_type
43  use m_atomdata,     only : atom_length
44  use m_mpinfo,       only : ptabs_fourdp, proc_distrb_cycle
45  use m_pawtab,       only : pawtab_type
46  use m_io_tools,     only : open_file
47  use m_splines,      only : spline, splint
48  use m_sort,         only : sort_dp
49  use m_prep_kgb,     only : prep_fourwf
50  use m_wvl_rho,      only : wvl_mkrho
51  use m_rot_cg,       only : rot_cg
52 
53 #if defined HAVE_YAKL
54  use gator_mod
55 #endif
56 
57 #ifdef HAVE_OPENMP_OFFLOAD
58  use m_ompgpu_fourwf
59 #endif
60 
61  implicit none
62 
63  private

m_mkrho/mkrho [ Functions ]

[ Top ] [ m_mkrho ] [ Functions ]

NAME

 mkrho

FUNCTION

 Depending on option argument value:
 --Compute charge density rho(r) and rho(G) in electrons/bohr**3
   from input wavefunctions, band occupations, and k point wts.
 --Compute kinetic energy density tau(r) and tau(G) in bohr**-5
   from input wavefunctions, band occupations, and k point wts.
 --Compute a given element of the kinetic energy density tensor
   tau_{alpha,beta}(r) and tau_{alpha,beta}(G) in bohr**-5
   from input wavefunctions, band occupations, and k point wts.

INPUTS

  cg(2,mcg)=wf in G space
  dtset <type(dataset_type)>=all input variables for this dataset
   | istwfk(nkpt)=input option parameter that describes the storage of wfs
   | mband=maximum number of bands
   | mgfft=maximum size of 1D FFTs
   | mkmem=Number of k points treated by this node
   | mpw=maximum allowed value for npw
   | nband(nkpt*nsppol)=number of bands to be included in summation
   |  at each k point for each spin channel
   | nfft=(effective) number of FFT grid points (for this processor)
   | ngfft(18)=contain all needed information about 3D FFT,
   |  see ~abinit/doc/variables/vargs.htm#ngfft
   | nkpt=number of k points
   | nspden=number of spin-density components
   | nsppol=1 for unpolarized, 2 for spin-polarized
   | nsym=number of symmetry elements in group (at least 1 for identity)
   | symafm(nsym)=(anti)ferromagnetic part of symmetry operations
   | symrel(3,3,nsym)=symmetry matrices in real space (integers)
   | wtk(nkpt)=k point weights (they sum to 1.0)
  gprimd(3,3)=dimensional reciprocal space primitive translations
  irrzon(nfft**(1-1/nsym),2,(nspden/nsppol)-3*(nspden/4))=irreducible zone data
  kg(3,mpw*mkmem)=reduced planewave coordinates
  mcg=size of wave-functions array (cg) =mpw*nspinor*mband*mkmem*nsppol
  mpi_enreg=information about MPI parallelization
  npwarr(nkpt)=number of planewaves and boundary planewaves at each k
  occ(mband*nkpt*nsppol)=
          occupation numbers for each band (usually 2.0) at each k point
  option if 0: compute rhor (electron density)
         if 1: compute taur (kinetic energy density)
               (i.e. Trace over the kinetic energy density tensor)
         if 2: compute taur_{alpha,beta} !!NOT YET IMPLEMENTED
               (a given element of the kinetic energy density tensor)
  paw_dmft  <type(paw_dmft_type)>= paw+dmft related data
  phnons(2,nfft**(1-1/nsym),(nspden/nsppol)-3*(nspden/4))=nonsymmorphic translation phases
  rprimd(3,3)=dimensional real space primitive translations
  tim_mkrho=timing code of the calling routine(can be set to 0 if not attributed)
  ucvol=unit cell volume (Bohr**3)
  wvl_den <type(wvl_denspot_type)>=density information for wavelets
  wvl_wfs <type(wvl_projector_type)>=wavefunctions information for wavelets

OUTPUT

 rhog(2,nfft)=total electron density in G space
 rhor(nfft,nspden)=electron density in r space
   (if spin polarized, array contains total density in first half and spin-up density in second half)
   (for non-collinear magnetism, first element: total density, 3 next ones: mx,my,mz in units of hbar/2)

SOURCE

138 subroutine mkrho(cg,dtset,gprimd,irrzon,kg,mcg,mpi_enreg,npwarr,occ,paw_dmft,phnons,&
139 &                rhog,rhor,rprimd,tim_mkrho,ucvol,wvl_den,wvl_wfs,&
140 &                extfpmd,option) !optional
141 
142 !Arguments ------------------------------------
143 !scalars
144  integer,intent(in) :: mcg,tim_mkrho
145  integer,intent(in),optional :: option
146  real(dp),intent(in) :: ucvol
147  type(extfpmd_type),intent(in),pointer,optional :: extfpmd
148  type(MPI_type),intent(inout) :: mpi_enreg
149  type(dataset_type),intent(in) :: dtset
150  type(paw_dmft_type), intent(in)  :: paw_dmft
151  type(wvl_wf_type),intent(inout) :: wvl_wfs
152  type(wvl_denspot_type), intent(inout) :: wvl_den
153 !no_abirules
154 !nfft**(1-1/nsym) is 1 if nsym==1, and nfft otherwise
155  integer, intent(in) :: irrzon(dtset%nfft**(1-1/dtset%nsym),2,  &
156    &               (dtset%nspden/dtset%nsppol)-3*(dtset%nspden/4))
157  integer, intent(in) :: kg(3,dtset%mpw*dtset%mkmem),npwarr(dtset%nkpt)
158  real(dp), intent(in) :: gprimd(3,3)
159  real(dp), intent(in) :: cg(2,mcg)
160  real(dp), intent(in) :: occ(dtset%mband*dtset%nkpt*dtset%nsppol)
161 !nfft**(1-1/nsym) is 1 if nsym==1, and nfft otherwise
162  real(dp), intent(in) :: phnons(2,(dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3))**(1-1/dtset%nsym),  &
163 &                                 (dtset%nspden/dtset%nsppol)-3*(dtset%nspden/4))
164  real(dp), intent(in) :: rprimd(3,3)
165  real(dp), intent(out) :: rhor(dtset%nfft,dtset%nspden),rhog(2,dtset%nfft)
166 
167 !Local variables-------------------------------
168 !scalars
169  integer,save :: nskip=0
170  integer :: alpha,use_nondiag_occup_dmft,bdtot_index,beta,blocksize,iband,iband1,ibandc1,ib,iblock,icg,ierr
171  integer :: ifft,ikg,ikpt,ioption,ipw,ipwbd,ipwsp,ishf,ispden,ispinor,ispinor_index
172  integer :: isppol,istwf_k,jspinor_index
173  integer :: me,my_nspinor,n1,n2,n3,n4,n5,n6,nalpha,nband_k,nband_occ,nbandc1,nbdblock,nbeta
174  integer :: ndat,nfftot,npw_k,spaceComm,tim_fourwf
175  integer :: iband_me
176  integer :: mband_mem
177  real(dp) :: kpt_cart,kg_k_cart,gp2pi1,gp2pi2,gp2pi3,cwftmp
178  real(dp) :: weight,weight_i
179  !character(len=500) :: message
180 !arrays
181  integer,allocatable :: gbound(:,:)
182  integer, ABI_CONTIGUOUS pointer :: kg_k(:,:) => null()
183  logical :: locc_test,nspinor1TreatedByThisProc,nspinor2TreatedByThisProc
184  real(dp) :: dummy(2,1) = reshape( (/0.0, 0.0/), shape(dummy))
185  real(dp) :: tsec(2)
186  real(dp),allocatable :: cwavef_rot(:,:,:,:),occ_diag(:),occ_k(:)
187  real(dp),allocatable :: kg_k_cart_block(:),taur_alphabeta(:,:,:,:),weight_t(:)
188  real(dp), ABI_CONTIGUOUS pointer :: cwavef(:,:,:)  => null()
189  real(dp), ABI_CONTIGUOUS pointer :: cwavefb(:,:,:) => null()
190  real(dp), ABI_CONTIGUOUS pointer :: cwavef_x(:,:)  => null()
191  real(dp), ABI_CONTIGUOUS pointer :: cwavef_y(:,:)  => null()
192  real(dp), ABI_CONTIGUOUS pointer :: cwavefb_x(:,:) => null() ! only use when paral_kgb=0
193  real(dp), ABI_CONTIGUOUS pointer :: cwavefb_y(:,:) => null() ! only use when paral_kgb=0
194  real(dp), ABI_CONTIGUOUS pointer :: rhoaug(:,:,:)      => null()
195  real(dp), ABI_CONTIGUOUS pointer :: rhoaug_down(:,:,:) => null()
196  real(dp), ABI_CONTIGUOUS pointer :: rhoaug_up(:,:,:)   => null()
197  real(dp), ABI_CONTIGUOUS pointer :: rhoaug_mx(:,:,:)   => null()
198  real(dp), ABI_CONTIGUOUS pointer :: rhoaug_my(:,:,:)   => null()
199  real(dp), ABI_CONTIGUOUS pointer :: wfraug(:,:,:,:)    => null()
200 
201 ! *************************************************************************
202 
203  DBG_ENTER("COLL")
204 
205  call timab(790+tim_mkrho,1,tsec)
206  call timab(799,1,tsec)
207 
208  if(mpi_enreg%paralbd==0) tim_fourwf=3
209  if(mpi_enreg%paralbd==1) tim_fourwf=6
210 
211  if(.not.(present(option))) then
212    ioption=0
213  else
214    ioption=option
215  end if
216 
217  if(ioption/=0.and.paw_dmft%use_sc_dmft==1) then
218    ABI_ERROR('option argument value of this routines should be 0 if usedmft=1.')
219  end if
220  if(paw_dmft%use_sc_dmft/=0) then
221    nbandc1=(paw_dmft%mbandc-1)*paw_dmft%use_sc_dmft+1
222  else
223    nbandc1=1
224  end if
225  use_nondiag_occup_dmft=0
226 
227 !if(dtset%nspinor==2.and.paw_dmft%use_sc_dmft==1) then
228 !write(message, '(a,a,a,a)' )ch10,&
229 !&   ' mkrho : ERROR -',ch10,&
230 !&   '  nspinor argument value of this routines should be 1 if usedmft=1. '
231 !call wrtout(std_out,message,'COLL')
232 !end if
233 
234  my_nspinor=max(1,dtset%nspinor/mpi_enreg%nproc_spinor)
235  if (mpi_enreg%paral_spinor==0) then
236    ispinor_index=1;jspinor_index=1
237    nspinor1TreatedByThisProc=.true.
238    nspinor2TreatedByThisProc=(dtset%nspinor==2)
239  else
240    ispinor_index=mpi_enreg%me_spinor+1;jspinor_index=3-ispinor_index
241    nspinor1TreatedByThisProc=(mpi_enreg%me_spinor==0)
242    nspinor2TreatedByThisProc=(mpi_enreg%me_spinor==1)
243  end if
244 
245 !Set local variable which depend on option argument
246 
247 !nalpha*nbeta is the number of element of the kinetic energy density tensor
248 !to be computed in the irreducible Brillouin Zone (BZ) to get the result in the full BZ.
249 !In case of electron density calculation, nalpha=nbeta=1
250  select case (ioption)
251  case (0)
252    nalpha = 1
253    nbeta = 1
254  case (1)
255    nalpha = 3
256    nbeta = 1
257    ABI_MALLOC(taur_alphabeta,(dtset%nfft,dtset%nspden,3,1))
258  case (2)
259    nalpha = 3
260    nbeta = 3
261    ABI_MALLOC(taur_alphabeta,(dtset%nfft,dtset%nspden,3,3))
262  case default
263    ABI_BUG(sjoin('ioption argument value should be 0,1 or 2 while got:', itoa(ioption)))
264  end select
265 
266 !Init me
267  me=mpi_enreg%me_kpt
268 !zero the charge density array in real space
269 !$OMP PARALLEL DO COLLAPSE(2)
270  do ispden=1,dtset%nspden
271    do ifft=1,dtset%nfft
272      rhor(ifft,ispden)=zero
273    end do
274  end do
275 
276 !WVL - Branching with a separate mkrho procedure in wavelet.
277  if (dtset%usewvl == 1) then
278    select case(ioption)
279    case (0)
280      call wvl_mkrho(dtset, irrzon, mpi_enreg, phnons, rhor, wvl_wfs, wvl_den)
281      return
282    case (1)
283      !call wvl_mkrho(dtset, mpi_enreg, occ, rhor, wvl_wfs, wvl_den)
284      ABI_ERROR("kinetic energy density (taur) is not yet implemented in wavelet formalism.")
285    case (2)
286      !call wvl_mkrho(dtset, mpi_enreg, occ, rhor, wvl_wfs, wvl_den)
287      ABI_BUG('kinetic energy density tensor (taur_(alpha,beta)) is not yet implemented in wavelet formalism.')
288    end select
289  end if
290 !WVL - Following is done in plane waves.
291 
292 !start loop over alpha and beta
293 
294  do alpha=1,nalpha
295    do beta=1,nbeta
296 
297      ! start loop over spin and k points
298      bdtot_index=0
299      icg=0
300 
301      ! n4,n5,n6 are FFT dimensions, modified to avoid cache trashing
302      n1 = dtset%ngfft(1) ; n2 = dtset%ngfft(2) ; n3 = dtset%ngfft(3)
303      n4 = dtset%ngfft(4) ; n5 = dtset%ngfft(5) ; n6 = dtset%ngfft(6)
304 
305      ndat = 1
306      if (mpi_enreg%paral_kgb==1) then
307        ndat = mpi_enreg%bandpp
308      else if (dtset%gpu_option/=ABI_GPU_DISABLED) then
309        ndat = dtset%mband
310      end if
311 
312      if (dtset%gpu_option == ABI_GPU_KOKKOS) then
313 #if defined HAVE_GPU && defined HAVE_YAKL
314        ABI_MALLOC_MANAGED(cwavef,(/2,dtset%mpw*ndat,my_nspinor/))
315 #endif
316      else
317        if (dtset%gpu_option/=ABI_GPU_DISABLED) then
318          ABI_MALLOC(cwavef,(2,dtset%mpw*ndat,my_nspinor))
319        else
320          ABI_MALLOC(cwavef,(2,dtset%mpw,my_nspinor))
321        end if
322      end if
323 
324      if(dtset%gpu_option == ABI_GPU_KOKKOS) then
325 #if defined HAVE_GPU && defined HAVE_YAKL
326        ABI_MALLOC_MANAGED(rhoaug,  (/n4,n5,n6/))
327        ABI_MALLOC_MANAGED(wfraug,  (/2,n4,n5,n6*ndat/))
328        ABI_MALLOC_MANAGED(cwavefb, (/2,dtset%mpw*paw_dmft%use_sc_dmft,my_nspinor/))
329        if(dtset%nspden==4) then
330          ABI_MALLOC_MANAGED(rhoaug_up,  (/n4,n5,n6/))
331          ABI_MALLOC_MANAGED(rhoaug_down,(/n4,n5,n6/))
332          ABI_MALLOC_MANAGED(rhoaug_mx,  (/n4,n5,n6/))
333          ABI_MALLOC_MANAGED(rhoaug_my,  (/n4,n5,n6/))
334          rhoaug_up(:,:,:)=zero
335          rhoaug_down(:,:,:)=zero
336          rhoaug_mx(:,:,:)=zero
337          rhoaug_my(:,:,:)=zero
338        end if
339 #endif
340      else
341        ABI_MALLOC(rhoaug,  (n4,n5,n6))
342        ABI_MALLOC(wfraug,  (2,n4,n5,n6*ndat))
343        ABI_MALLOC(cwavefb,  (2,dtset%mpw*paw_dmft%use_sc_dmft,my_nspinor))
344        if(dtset%nspden==4) then
345          ABI_MALLOC(rhoaug_up,  (n4,n5,n6))
346          ABI_MALLOC(rhoaug_down,(n4,n5,n6))
347          ABI_MALLOC(rhoaug_mx,  (n4,n5,n6))
348          ABI_MALLOC(rhoaug_my,  (n4,n5,n6))
349          rhoaug_up(:,:,:)=zero
350          rhoaug_down(:,:,:)=zero
351          rhoaug_mx(:,:,:)=zero
352          rhoaug_my(:,:,:)=zero
353        end if
354      end if
355 
356      do isppol=1,dtset%nsppol
357        ikg=0
358 
359        rhoaug(:,:,:)=zero
360        do ikpt=1,dtset%nkpt
361 
362          nband_k = dtset%nband(ikpt+(isppol-1)*dtset%nkpt)
363          mband_mem = nband_k
364          if (dtset%paral_kgb==0) mband_mem = nband_k/mpi_enreg%nproc_band
365          npw_k=npwarr(ikpt)
366          istwf_k = dtset%istwfk(ikpt)
367 
368          if(proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,me)) then
369            bdtot_index=bdtot_index+nband_k
370            cycle
371          end if
372 
373          ABI_MALLOC(gbound,(2*dtset%mgfft+8,2))
374          if(dtset%gpu_option == ABI_GPU_KOKKOS) then
375 #if defined HAVE_GPU && defined HAVE_YAKL
376            ABI_MALLOC_MANAGED(kg_k, (/3,npw_k/))
377 #endif
378          else
379            ABI_MALLOC(kg_k,(3,npw_k))
380          end if
381 
382          kg_k(:,1:npw_k)=kg(:,1+ikg:npw_k+ikg)
383          call sphereboundary(gbound,istwf_k,kg_k,dtset%mgfft,npw_k)
384 
385 !        Loop over bands to fft and square for rho(r)
386 !        Should be changed to treat bands by batch always
387 
388          if (mpi_enreg%paral_kgb /= 1) then  ! Not yet parallelized on spinors
389 
390 #ifdef HAVE_OPENMP_OFFLOAD
391            ! With OpenMP GPU, uploading kg_k when paral_kgb==0
392            !$OMP TARGET ENTER DATA MAP(to:kg_k) IF(dtset%gpu_option==ABI_GPU_OPENMP)
393 #endif
394 
395            if (dtset%gpu_option /= ABI_GPU_DISABLED) then
396              !On GPU, treat all bands at once
397              ABI_MALLOC(weight_t,(nband_k))
398              nband_occ = 0
399              do iband=1,nband_k
400                ipwsp = (iband-1)*npw_k*my_nspinor + icg
401                weight_t(iband) = occ(iband+bdtot_index) * dtset%wtk(ikpt)/ucvol
402                locc_test = abs(occ(iband+bdtot_index))>tol8
403                if (locc_test) then
404                  nband_occ = nband_occ +1
405                  ipwbd = (nband_occ-1) * npw_k
406                  cwavef(:,ipwbd+1:ipwbd+npw_k,1) = cg(:,ipwsp+1:ipwsp+npw_k)
407                  if (my_nspinor==2) cwavef(:,ipwbd+1:ipwbd+npw_k,2) = cg(:,ipwsp+npw_k+1:ipwsp+npw_k+npw_k)
408                  if (ioption==1) then ! Multiplication by 2pi i (k+G)_alpha
409                    gp2pi2 = gprimd(alpha,2)*two_pi ; gp2pi2 = gprimd(alpha,2)*two_pi ; gp2pi3 = gprimd(alpha,3)*two_pi
410                    kpt_cart = gp2pi1*dtset%kptns(1,ikpt) + gp2pi2*dtset%kptns(2,ikpt) + gp2pi3*dtset%kptns(3,ikpt)
411                    do ispinor=1,my_nspinor
412                      do ipw=1,npw_k
413                        kg_k_cart = gp2pi1*kg_k(1,ipw) + gp2pi2*kg_k(2,ipw) + gp2pi3*kg_k(3,ipw) + kpt_cart
414                        cwftmp = -cwavef(2,ipwbd+ipw,ispinor)*kg_k_cart
415                        cwavef(2,ipwbd+ipw,ispinor) = cwavef(1,ipwbd+ipw,ispinor)*kg_k_cart
416                        cwavef(1,ipwbd+ipw,ispinor) = cwftmp
417                      end do
418                    end do
419                  else if (ioption==2) then
420                    ABI_ERROR('kinetic energy density tensor (taur_(alpha,beta)) is not yet implemented.')
421                  end if ! end if ioption==1
422                end if ! end if locc_test
423              end do ! end iband=1,nband_k
424              if (nband_occ>0) then
425                call fourwf(1,rhoaug,cwavef(:,1:nband_occ*npw_k,1),dummy,wfraug(:,:,:,1:n6*nband_occ),&
426 &                gbound,gbound,istwf_k,kg_k,kg_k,dtset%mgfft,mpi_enreg,nband_occ,dtset%ngfft,&
427 &                npw_k,1,n4,n5,n6,1,tim_fourwf,weight,weight_i,&
428 &                weight_array_r=weight_t(1:nband_occ),weight_array_i=weight_t(1:nband_occ),&
429 &                gpu_option=dtset%gpu_option)
430              end if
431              ABI_FREE(weight_t)
432 
433            else ! CPU version
434 
435              iband_me = 0
436              do iband=1,nband_k
437                if(mpi_enreg%paralbd==1)then
438                  if(proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,iband,iband,isppol,me)) cycle
439                end if
440                iband_me = iband_me + 1
441                do ibandc1=1,nbandc1 ! in case of DMFT
442                  ! Check if DMFT and only treat occupied states (check on occ.)
443                  if(paw_dmft%use_sc_dmft == 1) then
444                    iband1 = paw_dmft%include_bands(ibandc1)
445                    if(paw_dmft%band_in(iband)) then
446                      if(.not. paw_dmft%band_in(iband1))  stop
447                      use_nondiag_occup_dmft = 1
448                      locc_test = abs(paw_dmft%occnd(1,iband,iband1,ikpt,isppol)) +&
449                        &                   abs(paw_dmft%occnd(2,iband,iband1,ikpt,isppol))>tol8
450                    else
451                      use_nondiag_occup_dmft = 0
452                      locc_test = abs(occ(iband+bdtot_index))>tol8
453                      if(ibandc1 /=1 .and. .not. paw_dmft%band_in(iband)) cycle
454                    end if
455                  else
456                    use_nondiag_occup_dmft = 0
457                    locc_test = abs(occ(iband+bdtot_index))>tol8
458                  end if
459                  if (locc_test) then
460                    ! Obtain Fourier transform in fft box and accumulate the density or
461                    ! the kinetic energy density
462                    ! Not yet parallelized on nspinor if paral_kgb/=1
463                    ipwsp=(iband_me-1)*npw_k*my_nspinor +icg
464                    cwavef(:,1:npw_k,1) =                  cg(:,1+ipwsp      :ipwsp+npw_k)
465                    if (my_nspinor==2) cwavef(:,1:npw_k,2)=cg(:,1+ipwsp+npw_k:ipwsp+2*npw_k)
466                    if(ioption==1)then
467                      ! Multiplication by 2pi i (k+G)_alpha
468                      gp2pi1=gprimd(alpha,1)*two_pi ; gp2pi2=gprimd(alpha,2)*two_pi ; gp2pi3=gprimd(alpha,3)*two_pi
469                      kpt_cart=gp2pi1*dtset%kptns(1,ikpt)+gp2pi2*dtset%kptns(2,ikpt)+gp2pi3*dtset%kptns(3,ikpt)
470                      do ispinor=1,my_nspinor
471                        do ipw=1,npw_k
472                          kg_k_cart=gp2pi1*kg_k(1,ipw)+gp2pi2*kg_k(2,ipw)+gp2pi3*kg_k(3,ipw)+kpt_cart
473                          cwftmp=-cwavef(2,ipw,ispinor)*kg_k_cart
474                          cwavef(2,ipw,ispinor)=cwavef(1,ipw,ispinor)*kg_k_cart
475                          cwavef(1,ipw,ispinor)=cwftmp
476                        end do
477                      end do
478                    else if(ioption==2)then
479                      ABI_ERROR('kinetic energy density tensor (taur_(alpha,beta)) is not yet implemented.')
480                    end if
481                    ! Non diag occupation in DMFT.
482                    ! TODO : this will break in full distrib of band memory
483                    if(use_nondiag_occup_dmft==1) then
484                      ipwsp=(iband1-1)*npw_k*my_nspinor +icg
485                      cwavefb(:,1:npw_k,1)=cg(:,1+ipwsp:ipwsp+npw_k)
486                      if (my_nspinor==2) cwavefb(:,1:npw_k,2)=cg(:,ipwsp+npw_k+1:ipwsp+2*npw_k)
487                      weight  =paw_dmft%occnd(1,iband,iband1,ikpt,isppol)*dtset%wtk(ikpt)/ucvol
488                      weight_i=paw_dmft%occnd(2,iband,iband1,ikpt,isppol)*dtset%wtk(ikpt)/ucvol
489                    else
490                      weight=occ(iband+bdtot_index)*dtset%wtk(ikpt)/ucvol
491                      weight_i=weight
492                    end if
493 
494                    ! The same section of code is also found in vtowfk.F90 : should be rationalized !
495 
496                    call fourwf(1,rhoaug,cwavef(:,:,1),dummy,wfraug,gbound,gbound,&
497                      &                 istwf_k,kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,&
498                      &                 npw_k,1,n4,n5,n6,1,tim_fourwf,weight,weight_i,&
499                      &                 use_ndo=use_nondiag_occup_dmft,fofginb=cwavefb(:,:,1),&
500                      &                 gpu_option=dtset%gpu_option)
501                    if(dtset%nspinor==2)then
502                      if(dtset%nspden==1) then
503                        ! We need only the total density : accumulation continues on top of rhoaug
504                        call fourwf(1,rhoaug,cwavef(:,:,2),dummy,wfraug,gbound,gbound,&
505                          &                     istwf_k,kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,&
506                          &                     npw_k,1,n4,n5,n6,1,tim_fourwf,weight,weight_i,&
507                          &                     use_ndo=use_nondiag_occup_dmft,fofginb=cwavefb(:,:,2),&
508                          &                     gpu_option=dtset%gpu_option)
509                      else if(dtset%nspden==4) then
510                        ! Build the four components of rho. We use only norm quantities and, so fourwf.
511                        ! $\sum_{n} f_n \Psi^{* \alpha}_n \Psi^{\alpha}_n =\rho^{\alpha \alpha}$
512                        ! $\sum_{n} f_n (\Psi^{1}+\Psi^{2})^*_n (\Psi^{1}+\Psi^{2})_n=rho+m_x$
513                        ! $\sum_{n} f_n (\Psi^{1}-i \Psi^{2})^*_n (\Psi^{1}-i \Psi^{2})_n=rho+m_y$
514                        if(dtset%gpu_option == ABI_GPU_KOKKOS) then
515 #if defined HAVE_GPU && defined HAVE_YAKL
516                          ABI_MALLOC_MANAGED(cwavef_x, (/2,npw_k/))
517                          ABI_MALLOC_MANAGED(cwavef_y, (/2,npw_k/))
518                          ABI_MALLOC_MANAGED(cwavefb_x,(/2,npw_k*paw_dmft%use_sc_dmft/))
519                          ABI_MALLOC_MANAGED(cwavefb_y,(/2,npw_k*paw_dmft%use_sc_dmft/))
520 #endif
521                        else
522                          ABI_MALLOC(cwavef_x,(2,npw_k))
523                          ABI_MALLOC(cwavef_y,(2,npw_k))
524                          ABI_MALLOC(cwavefb_x,(2,npw_k*paw_dmft%use_sc_dmft))
525                          ABI_MALLOC(cwavefb_y,(2,npw_k*paw_dmft%use_sc_dmft))
526                        end if
527                        ! $(\Psi^{1}+\Psi^{2})$
528                        cwavef_x(:,:)=cwavef(:,1:npw_k,1)+cwavef(:,1:npw_k,2)
529                        ! $(\Psi^{1}-i \Psi^{2})$
530                        cwavef_y(1,:)=cwavef(1,1:npw_k,1)+cwavef(2,1:npw_k,2)
531                        cwavef_y(2,:)=cwavef(2,1:npw_k,1)-cwavef(1,1:npw_k,2)
532                        if(use_nondiag_occup_dmft==1) then
533                          cwavefb_x(:,:)=cwavefb(:,1:npw_k,1)+cwavefb(:,1:npw_k,2)
534                          cwavefb_y(1,:)=cwavefb(1,1:npw_k,1)+cwavefb(2,1:npw_k,2)
535                          cwavefb_y(2,:)=cwavefb(2,1:npw_k,1)-cwavefb(1,1:npw_k,2)
536                        end if
537                        rhoaug_up(:,:,:)=rhoaug(:,:,:) !Already computed
538                        call fourwf(1,rhoaug_down,cwavef(:,:,2),dummy,wfraug,gbound,gbound,&
539                          &                     istwf_k,kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,&
540                          &                     npw_k,1,n4,n5,n6,1,tim_fourwf,weight,weight_i,&
541                          &                     use_ndo=use_nondiag_occup_dmft,fofginb=cwavefb(:,:,2),&
542                          &                     gpu_option=dtset%gpu_option)
543 
544                        call fourwf(1,rhoaug_mx,cwavef_x,dummy,wfraug,gbound,gbound,&
545                          &                     istwf_k,kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,&
546                          &                     npw_k,1,n4,n5,n6,1,tim_fourwf,weight,weight_i,&
547                          &                     use_ndo=use_nondiag_occup_dmft,fofginb=cwavefb_x,&
548                          &                     gpu_option=dtset%gpu_option)
549 
550                        call fourwf(1,rhoaug_my,cwavef_y,dummy,wfraug,gbound,gbound,&
551                          &                     istwf_k,kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,&
552                          &                     npw_k,1,n4,n5,n6,1,tim_fourwf,weight,weight_i,&
553                          &                     use_ndo=use_nondiag_occup_dmft,fofginb=cwavefb_y,&
554                          &                     gpu_option=dtset%gpu_option)
555                        if(dtset%gpu_option == ABI_GPU_KOKKOS) then
556 #if defined HAVE_GPU && defined HAVE_YAKL
557                          ABI_FREE_MANAGED(cwavef_x)
558                          ABI_FREE_MANAGED(cwavef_y)
559                          ABI_FREE_MANAGED(cwavefb_x)
560                          ABI_FREE_MANAGED(cwavefb_y)
561 #endif
562                        else
563                          ABI_FREE(cwavef_x)
564                          ABI_FREE(cwavef_y)
565                          ABI_FREE(cwavefb_x)
566                          ABI_FREE(cwavefb_y)
567                        end if
568                      end if ! dtset%nspden/=4
569                    end if
570                  else
571                    ! Accumulate the number of one-way 3D ffts skipped
572                    nskip=nskip+1
573                  end if ! abs(occ(iband+bdtot_index))>tol8
574                end do ! iband1=1,(nband_k-1)*paw_dmft%use_sc_dmft+1
575              end do ! iband=1,nband_k
576 
577            end if ! gpu_option
578 
579 #ifdef HAVE_OPENMP_OFFLOAD
580            !$OMP TARGET EXIT DATA MAP(delete:kg_k) IF(dtset%gpu_option==ABI_GPU_OPENMP)
581 #endif
582          else !paral_kgb==1
583 
584            if(proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,me)) cycle
585 
586            call bandfft_kpt_set_ikpt(ikpt,mpi_enreg)
587            nbdblock=nband_k/(mpi_enreg%nproc_band * mpi_enreg%bandpp)
588            blocksize=nband_k/nbdblock
589 
590            if(dtset%gpu_option == ABI_GPU_KOKKOS) then
591 #if defined HAVE_GPU && defined HAVE_YAKL
592              if(associated(cwavef))  then
593                ABI_FREE_MANAGED(cwavef)
594              end if
595              ABI_MALLOC_MANAGED(cwavef,(/2,npw_k*blocksize,dtset%nspinor/))
596 #endif
597            else
598              if(associated(cwavef))  then
599                ABI_FREE(cwavef)
600              end if
601              ABI_MALLOC(cwavef,(2,npw_k*blocksize,dtset%nspinor))
602            end if
603            if(ioption==1)  then
604              ABI_MALLOC(kg_k_cart_block,(npw_k))
605            end if
606            ABI_MALLOC(occ_k,(nband_k))
607            occ_k(:)=occ(bdtot_index+1:bdtot_index+nband_k)
608 
609 ! ---------- DMFT
610            if(allocated(cwavef_rot))  then
611              ABI_FREE(cwavef_rot)
612              ABI_FREE(occ_diag)
613              ! ABI_FREE(occ_nd)
614            end if
615            if(paw_dmft%use_sc_dmft==1) then
616              ! Allocation of DMFT temporaries arrays
617              ABI_MALLOC(cwavef_rot,(2,npw_k,blocksize,dtset%nspinor))
618              ABI_MALLOC(occ_diag,(blocksize))
619              ! ABI_MALLOC(occ_nd,(2, blocksize, blocksize, dtset%nspinor))
620            end if
621 ! ---------- END DMFT
622 
623            do iblock=1,nbdblock
624              if (dtset%nspinor==1) then
625                cwavef(:,1:npw_k*blocksize,1)=cg(:,1+(iblock-1)*npw_k*blocksize+icg:iblock*npw_k*blocksize+icg)
626              else
627                if (mpi_enreg%paral_spinor==0) then
628                  ishf=(iblock-1)*npw_k*my_nspinor*blocksize+icg
629                  do ib=1,blocksize
630                    cwavef(:,(ib-1)*npw_k+1:ib*npw_k,1)=cg(:,1+(2*ib-2)*npw_k+ishf:(2*ib-1)*npw_k+ishf)
631                    cwavef(:,(ib-1)*npw_k+1:ib*npw_k,2)=cg(:,1+(2*ib-1)*npw_k+ishf:ib*2*npw_k+ishf)
632                  end do
633                else
634                  ishf=(iblock-1)*npw_k*my_nspinor*blocksize+icg
635                  do ib=1,blocksize
636                    cwavef(:,(ib-1)*npw_k+1:ib*npw_k,ispinor_index)=&
637 &                   cg(:,1+(ib-1)*npw_k+ishf:ib*npw_k+ishf)
638                    cwavef(:,(ib-1)*npw_k+1:ib*npw_k,jspinor_index)=zero
639                  end do
640                  call xmpi_sum(cwavef,mpi_enreg%comm_spinor,ierr)
641                end if
642              end if
643 
644              if(ioption==1)then
645 !              Multiplication by 2pi i (k+G)_alpha
646                gp2pi1=gprimd(alpha,1)*two_pi ; gp2pi2=gprimd(alpha,2)*two_pi ; gp2pi3=gprimd(alpha,3)*two_pi
647                kpt_cart=gp2pi1*dtset%kptns(1,ikpt)+gp2pi2*dtset%kptns(2,ikpt)+gp2pi3*dtset%kptns(3,ikpt)
648                kg_k_cart_block(1:npw_k)=gp2pi1*kg_k(1,1:npw_k)+gp2pi2*kg_k(2,1:npw_k)+gp2pi3*kg_k(3,1:npw_k)+kpt_cart
649                do ib=1,blocksize
650                  do ipw=1,npw_k
651                    cwftmp=-cwavef(2,ipw+(ib-1)*npw_k,1)*kg_k_cart_block(ipw)
652                    cwavef(2,ipw,1)=cwavef(1,ipw+(ib-1)*npw_k,1)*kg_k_cart_block(ipw)
653                    cwavef(1,ipw,1)=cwftmp
654                    if (my_nspinor==2) then
655                      cwftmp=-cwavef(2,ipw+(ib-1)*npw_k,2)*kg_k_cart_block(ipw)
656                      cwavef(2,ipw,2)=cwavef(1,ipw+(ib-1)*npw_k,2)*kg_k_cart_block(ipw)
657                      cwavef(1,ipw,2)=cwftmp
658                    end if
659                  end do
660                end do
661              else if(ioption==2)then
662                ABI_ERROR("kinetic energy density tensor (taur_(alpha,beta)) is not yet implemented.")
663              end if
664 
665 ! ---------- DMFT
666              if(paw_dmft%use_sc_dmft==1) then
667                ! initialisation of DMFT arrays
668                cwavef_rot(:,:,:,:) = zero
669                occ_diag(:) = zero
670                ! occ_nd(:,:,:,:) = paw_dmft%occnd(:,:,:,ikpt,:)
671 
672                do ib=1,blocksize
673                  cwavef_rot(:, :, ib, :) = cwavef(:, 1+(ib-1)*npw_k:ib*npw_k, :)
674                end do
675 
676                call rot_cg(paw_dmft%occnd(:,:,:,ikpt,isppol), cwavef_rot, npw_k, nband_k, blocksize,&
677 &                          dtset%nspinor, paw_dmft%include_bands(1), paw_dmft%mbandc, occ_diag)
678                do ib=1,blocksize
679                  cwavef(:, 1+(ib-1)*npw_k:ib*npw_k, :) = cwavef_rot(:, :, ib, :)
680                end do
681 
682                occ_k(:) = occ_diag(:)
683              end if
684 ! ---------- END DMFT
685 
686              call timab(538,1,tsec)
687              if (nspinor1TreatedByThisProc) then
688                call prep_fourwf(rhoaug,blocksize,cwavef(:,:,1),wfraug,iblock,istwf_k,dtset%mgfft,mpi_enreg,&
689 &               nband_k,ndat,dtset%ngfft,npw_k,n4,n5,n6,occ_k,1,ucvol,&
690 &               dtset%wtk(ikpt),gpu_option=dtset%gpu_option)
691              end if
692              call timab(538,2,tsec)
693              if(dtset%nspinor==2)then
694                if (dtset%nspden==1) then
695                  if (nspinor2TreatedByThisProc) then
696                    call prep_fourwf(rhoaug,blocksize,cwavef(:,:,2),wfraug,&
697 &                   iblock,istwf_k,dtset%mgfft,mpi_enreg,&
698 &                   nband_k,ndat,dtset%ngfft,npw_k,n4,n5,n6,occ_k,1,ucvol,&
699 &                   dtset%wtk(ikpt),gpu_option=dtset%gpu_option)
700                  end if
701                else if(dtset%nspden==4 ) then
702 
703                  if(dtset%gpu_option == ABI_GPU_KOKKOS) then
704 #if defined HAVE_GPU && defined HAVE_YAKL
705                    ABI_MALLOC_MANAGED(cwavef_x,(/2,npw_k*blocksize/))
706                    ABI_MALLOC_MANAGED(cwavef_y,(/2,npw_k*blocksize/))
707 #endif
708                  else
709                    ABI_MALLOC(cwavef_x,(2,npw_k*blocksize))
710                    ABI_MALLOC(cwavef_y,(2,npw_k*blocksize))
711                  end if
712 
713                  cwavef_x(:,:)=cwavef(:,:,1)+cwavef(:,:,2)
714                  cwavef_y(1,:)=cwavef(1,:,1)+cwavef(2,:,2)
715                  cwavef_y(2,:)=cwavef(2,:,1)-cwavef(1,:,2)
716 
717                  call timab(538,1,tsec)
718                  if (nspinor1TreatedByThisProc) then
719                    call prep_fourwf(rhoaug_down,blocksize,cwavef(:,:,2),wfraug,&
720 &                   iblock,istwf_k,dtset%mgfft,mpi_enreg,&
721 &                   nband_k,ndat,dtset%ngfft,npw_k,n4,n5,n6,occ_k,1,ucvol,&
722 &                   dtset%wtk(ikpt),gpu_option=dtset%gpu_option)
723                  end if
724                  if (nspinor2TreatedByThisProc) then
725                    call prep_fourwf(rhoaug_mx,blocksize,cwavef_x,wfraug,&
726 &                   iblock,istwf_k,dtset%mgfft,mpi_enreg,&
727 &                   nband_k,ndat,dtset%ngfft,npw_k,n4,n5,n6,occ_k,1,ucvol,&
728 &                   dtset%wtk(ikpt),gpu_option=dtset%gpu_option)
729                    call prep_fourwf(rhoaug_my,blocksize,cwavef_y,wfraug,&
730 &                   iblock,istwf_k,dtset%mgfft,mpi_enreg,&
731 &                   nband_k,ndat,dtset%ngfft,npw_k,n4,n5,n6,occ_k,1,ucvol,&
732 &                   dtset%wtk(ikpt),gpu_option=dtset%gpu_option)
733                  end if
734                  call timab(538,2,tsec)
735 
736                  if(dtset%gpu_option == ABI_GPU_KOKKOS) then
737 #if defined HAVE_GPU && defined HAVE_YAKL
738                    ABI_FREE_MANAGED(cwavef_x)
739                    ABI_FREE_MANAGED(cwavef_y)
740 #endif
741                  else
742                    ABI_FREE(cwavef_x)
743                    ABI_FREE(cwavef_y)
744                  end if
745 
746                end if
747              end if
748            end do !iblock
749            if(ioption==1)  then
750              ABI_FREE(kg_k_cart_block)
751            end if
752 
753            if (associated(cwavef))  then
754              if(dtset%gpu_option == ABI_GPU_KOKKOS) then
755 #if defined HAVE_GPU && defined HAVE_YAKL
756                ABI_FREE_MANAGED(cwavef)
757 #endif
758              else
759                ABI_FREE(cwavef)
760              end if
761            end if
762 
763            ABI_FREE(occ_k)
764          end if
765 
766          ABI_FREE(gbound)
767 
768          if(dtset%gpu_option == ABI_GPU_KOKKOS) then
769 #if defined HAVE_GPU && defined HAVE_YAKL
770            ABI_FREE_MANAGED(kg_k)
771 #endif
772          else
773            ABI_FREE(kg_k)
774          end if
775 
776          bdtot_index=bdtot_index+nband_k
777 
778          if (dtset%mkmem/=0) then
779            icg=icg+npw_k*my_nspinor*mband_mem !iband_me
780            ikg=ikg+npw_k
781          end if
782 
783        end do ! ikpt
784 
785        if(mpi_enreg%paral_kgb == 1) then
786          call bandfft_kpt_set_ikpt(-1,mpi_enreg)
787          if (dtset%nspden==4) then
788 !          Sum the contribution of the band and of the FFT
789            call xmpi_sum(rhoaug     ,mpi_enreg%comm_bandspinorfft, ierr)
790            call xmpi_sum(rhoaug_down,mpi_enreg%comm_bandspinorfft, ierr)
791            call xmpi_sum(rhoaug_mx ,mpi_enreg%comm_bandspinorfft, ierr)
792            call xmpi_sum(rhoaug_my ,mpi_enreg%comm_bandspinorfft, ierr)
793            rhoaug_up(:,:,:) = rhoaug(:,:,:)
794          else
795            call xmpi_sum(rhoaug,mpi_enreg%comm_bandspinorfft,ierr)
796          end if
797        end if
798 
799 !      Transfer density on augmented fft grid to normal fft grid in real space
800 !      Take also into account the spin, to place it correctly in rhor.
801        if(dtset%nspden==1 .or. dtset%nspden==2) then
802          call fftpac(isppol,mpi_enreg,dtset%nspden,n1,n2,n3,n4,n5,n6,dtset%ngfft,rhor,rhoaug,1)
803        else if(dtset%nspden==4) then
804          ispden=1
805          call fftpac(ispden,mpi_enreg,dtset%nspden,n1,n2,n3,n4,n5,n6,dtset%ngfft,rhor,rhoaug_up,1)
806          ispden=2
807          call fftpac(ispden,mpi_enreg,dtset%nspden,n1,n2,n3,n4,n5,n6,dtset%ngfft,rhor,rhoaug_mx,1)
808          ispden=3
809          call fftpac(ispden,mpi_enreg,dtset%nspden,n1,n2,n3,n4,n5,n6,dtset%ngfft,rhor,rhoaug_my,1)
810          ispden=4
811          call fftpac(ispden,mpi_enreg,dtset%nspden,n1,n2,n3,n4,n5,n6,dtset%ngfft,rhor,rhoaug_down,1)
812          if(dtset%gpu_option == ABI_GPU_KOKKOS) then
813 #if defined HAVE_GPU && defined HAVE_YAKL
814            ABI_FREE_MANAGED(rhoaug_up)
815            ABI_FREE_MANAGED(rhoaug_down)
816            ABI_FREE_MANAGED(rhoaug_mx)
817            ABI_FREE_MANAGED(rhoaug_my)
818 #endif
819          else
820            ABI_FREE(rhoaug_up)
821            ABI_FREE(rhoaug_down)
822            ABI_FREE(rhoaug_mx)
823            ABI_FREE(rhoaug_my)
824          end if
825        end if
826 
827      end do ! isppol
828 
829      if(dtset%gpu_option == ABI_GPU_KOKKOS) then
830 #if defined HAVE_GPU && defined HAVE_YAKL
831        if(associated(cwavef))  then
832          ABI_FREE_MANAGED(cwavef)
833        end if
834        if(associated(cwavefb))  then
835          ABI_FREE_MANAGED(cwavefb)
836        end if
837        ABI_FREE_MANAGED(rhoaug)
838        ABI_FREE_MANAGED(wfraug)
839 #endif
840      else
841        if(associated(cwavef))  then
842          ABI_FREE(cwavef)
843        end if
844        if(associated(cwavefb))  then
845          ABI_FREE(cwavefb)
846        endif
847        ABI_FREE(rhoaug)
848        ABI_FREE(wfraug)
849      end if
850 
851      if(allocated(cwavef_rot))  then
852        ABI_FREE(cwavef_rot)
853        ABI_FREE(occ_diag)
854        ! ABI_FREE(occ_nd)
855      end if
856 
857 !    Recreate full rhor on all proc.
858      call timab(48,1,tsec)
859      call timab(71,1,tsec)
860      spaceComm=mpi_enreg%comm_cell
861      if (mpi_enreg%paral_hf==1)spaceComm=mpi_enreg%comm_kpt
862      if(mpi_enreg%paral_kgb==1)spaceComm=mpi_enreg%comm_kpt
863      call xmpi_sum(rhor,spaceComm,ierr)
864      call timab(71,2,tsec)
865      call timab(48,2,tsec)
866 
867      call timab(799,2,tsec)
868      call timab(549,1,tsec)
869 
870      if(ioption==1 .or. ioption==2) then
871 !$OMP PARALLEL DO COLLAPSE(2)
872        do ispden=1,dtset%nspden
873          do ifft=1,dtset%nfft
874            taur_alphabeta(ifft,ispden,alpha,beta) = rhor(ifft,ispden)
875          end do
876        end do
877      end if
878 
879    end do !  beta=1,nbeta
880  end do !  alpha=1,nalpha
881 
882 !Compute the trace over the kinetic energy density tensor. i.e. Sum of the 3 diagonal elements.
883  if(ioption==1)then
884 !  zero rhor array in real space
885    do ispden=1,dtset%nspden
886 !$OMP PARALLEL DO
887      do ifft=1,dtset%nfft
888        rhor(ifft,ispden)=zero
889      end do
890    end do
891    do alpha = 1, nalpha
892 !$OMP PARALLEL DO COLLAPSE(2)
893      do ispden=1,dtset%nspden
894        do ifft=1,dtset%nfft
895          rhor(ifft,ispden) = rhor(ifft,ispden) + taur_alphabeta(ifft,ispden,alpha,1)
896        end do
897      end do
898    end do
899  end if
900 
901  nfftot=dtset%ngfft(1) * dtset%ngfft(2) * dtset%ngfft(3)
902 
903 !Add extfpmd free electrons contribution to density
904  if(present(extfpmd)) then
905    if(associated(extfpmd)) then
906      if(extfpmd%version==1.or.extfpmd%version==2.or.extfpmd%version==3.or.extfpmd%version==4) then
907        rhor(:,:)=rhor(:,:)+extfpmd%nelect/ucvol/dtset%nspden
908      else if(extfpmd%version==10) then
909        do ispden=1,dtset%nspden
910          do ifft=1,dtset%nfft
911            rhor(ifft,ispden)=rhor(ifft,ispden)+extfpmd%nelectarr(ifft,ispden)/ucvol/dtset%nspden
912          end do
913        end do
914      end if
915      rhog(1,1)=rhog(1,1)+extfpmd%nelect/ucvol/dtset%nspden
916    end if
917  end if
918 
919  select case (ioption)
920  case(0, 1)
921    call symrhg(1,gprimd,irrzon,mpi_enreg,dtset%nfft,nfftot,dtset%ngfft,dtset%nspden,dtset%nsppol,dtset%nsym,&
922                phnons,rhog,rhor,rprimd,dtset%symafm,dtset%symrel,dtset%tnons)
923    if(ioption==1)then
924 !$OMP PARALLEL DO
925      do ifft=1,dtset%nfft
926        do ispden=1,dtset%nspden
927          rhor(ifft,ispden)=1.0d0/2.0d0*rhor(ifft,ispden)
928        end do
929        rhog(:,ifft)=1.0d0/2.0d0*rhog(:,ifft)
930      end do
931    end if
932  case(2)
933    ABI_BUG('kinetic energy density tensor (taur_(alpha,beta)) is not yet implemented.')
934    !call symtaug(1,gprimd,irrzon,mpi_enreg,dtset%nfft,nfftot,dtset%ngfft,dtset%nspden,dtset%nsppol,dtset%nsym,&
935    !dtset%paral_kgb,phnons,rhog,rhor,rprimd,dtset%symafm,dtset%symrel)
936  end select
937 
938  call timab(549,2,tsec)
939 
940 !We now have both rho(r) and rho(G), symmetrized, and if dtset%nsppol=2
941 !we also have the spin-up density, symmetrized, in rhor(:,2).
942 !In case of non collinear magnetism, we have rho,mx,my,mz. No symmetry is applied
943 
944  call timab(799,1,tsec)
945 
946  if(ioption==1 .or. ioption==2)  then
947    ABI_FREE(taur_alphabeta)
948  end if
949 
950 !Find and print minimum and maximum total electron density
951 !(or total kinetic energy density, or total element of kinetic energy density tensor) and locations
952  call wrtout(std_out,' mkrho: echo density (plane-wave part only)','COLL')
953  call prtrhomxmn(std_out,mpi_enreg,dtset%nfft,dtset%ngfft,dtset%nspden,1,rhor,optrhor=ioption,ucvol=ucvol)
954 
955  call timab(799,2,tsec)
956  call timab(790+tim_mkrho,2,tsec)
957 
958  DBG_EXIT("COLL")
959 
960 end subroutine mkrho

m_mkrho/prtrhomxmn [ Functions ]

[ Top ] [ m_mkrho ] [ Functions ]

NAME

 prtrhomxmn

FUNCTION

 If option==1, compute the maximum and minimum of the density (and spin-polarization if nspden==2), and print it.
 If option==2, also compute and print the second maximum or minimum

INPUTS

  iout=unit for output file
  mpi_enreg=information about MPI parallelization
  nfft=(effective) number of FFT grid points (for this processor)
  ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
  nspden=number of spin-density components
  option, see above
  optrhor=option for rhor (If optrhor==0, rhor is expected to be the electron density)
                          (If optrhor==1, rhor is expected to be the kinetic energy density (taur))
                          (If optrhor==2, rhor is expected to be the gradient of the electron density (grhor))
                          (If optrhor==3, rhor is expected to be the laplacian of the electron density (lrhor))
                          (If optrhor==4, rhor is expected to be the ELF (elfr))
  rhor(nfft,nspden)=electron density (electrons/bohr^3)

NOTES

  The tolerance tol12 aims at giving a machine-independent ordering.
  (this trick is used in bonds.f, listkk.f, prtrhomxmn.f and rsiaf9.f)

SOURCE

1420 subroutine prtrhomxmn(iout,mpi_enreg,nfft,ngfft,nspden,option,rhor,optrhor,ucvol)
1421 
1422 !Arguments ------------------------------------
1423 !scalars
1424  integer,intent(in) :: iout,nfft,nspden,option
1425  type(MPI_type),intent(in) :: mpi_enreg
1426  integer,intent(in),optional :: optrhor
1427  real(dp),intent(in),optional :: ucvol
1428 !arrays
1429  integer,intent(in) :: ngfft(18)
1430  real(dp),intent(in) :: rhor(nfft,nspden)
1431 
1432 !Local variables-------------------------------
1433 !scalars
1434  integer :: i1,i2,i3,ierr,ifft,ii,iisign,iitems,index1,ioptrhor
1435  integer :: index2,indsign,iproc,istart,me,n1,n2,n3,nitems
1436  integer :: nfft_,nfftot,nproc,spaceComm
1437  real(dp) :: temp,value1,value2
1438  character(len=500) :: message,txt1_in_mssg,txt2_in_mssg,txt3_in_mssg
1439  logical :: reduce=.false.
1440 !arrays
1441  integer,allocatable :: iindex(:,:,:),index_fft(:,:,:,:)
1442  real(dp) :: rhomn1(4),rhomn2(4),rhomx1(4),rhomx2(4),ri_rhomn1(3,4)
1443  real(dp) :: ri_rhomn2(3,4),ri_rhomx1(3,4),ri_rhomx2(3,4),ri_zetmn1(3,2)
1444  real(dp) :: ri_zetmn2(3,2),ri_zetmx1(3,2),ri_zetmx2(3,2),zetmn1(2)
1445  real(dp) :: zetmn2(2),zetmx1(2),zetmx2(2)
1446  real(dp),allocatable :: array(:),coord(:,:,:,:),value(:,:,:),integrated(:)
1447  real(dp),allocatable :: value_fft(:,:,:)
1448 
1449 ! *************************************************************************
1450 
1451  if(.not.(present(optrhor))) then
1452    ioptrhor=0
1453  else
1454    ioptrhor=optrhor
1455  end if
1456 
1457  if(option/=1 .and. option/=2)then
1458    ABI_BUG(sjoin(' Option must be 1 or 2, while it is:', itoa(option)))
1459  end if
1460 
1461  if (mpi_enreg%nproc_wvl>1) then
1462 !  nfft is always the potential size (in GGA, the density has buffers).
1463    nfft_ = ngfft(1) * ngfft(2) * mpi_enreg%nscatterarr(mpi_enreg%me_wvl, 2)
1464    n1 = ngfft(1)
1465    n2 = ngfft(2)
1466    n3 = sum(mpi_enreg%nscatterarr(:, 2))
1467    istart = mpi_enreg%nscatterarr(mpi_enreg%me_wvl, 4)
1468  else
1469    nfft_ = nfft
1470    n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
1471    istart = 0
1472  end if
1473 
1474 !--------------------------------------------------------------------------
1475 !One has to determine the maximum and minimum (etc...) values
1476 !over all space, and then output it, as well as to identify
1477 !the point at which it occurs ...
1478 !This will require a bit of data exchange, and correct indirect indexing ...
1479 
1480 !For the local processor, find different items :
1481 !maximum and minimum total electron density and locations
1482 !and also spin-polarisation and magnetization
1483 !also keep the second maximal or minimal value
1484  if(nspden==1)nitems=1   ! Simply the total density
1485  if(nspden==2)nitems=5   ! Total density, spin up, spin down, magnetization, zeta
1486  if(nspden==4)nitems=6   ! Total density, x, y, z, magnetization, zeta
1487 
1488  ABI_MALLOC(value,(2,2,nitems))
1489  ABI_MALLOC(iindex,(2,2,nitems))
1490  ABI_MALLOC(array,(nfft))
1491  ABI_MALLOC(integrated,(nitems))
1492 
1493  do iitems=1,nitems
1494 
1495 !  Copy the correct values into the array
1496 !  First set of items : the density, for each spin component
1497    if(iitems<=nspden)then
1498      array(:)=rhor(:,iitems)
1499    end if
1500 !  Case nspden==2, some computation to be done
1501    if(nspden==2)then
1502      if(iitems==3)then ! Spin down
1503        array(:)=rhor(:,1)-rhor(:,2)
1504      else if(iitems==4)then  ! Magnetization
1505        array(:)=2*rhor(:,2)-rhor(:,1)
1506      else if(iitems==5)then  ! zeta = relative magnetization
1507        ! Avoid 0/0: the limit of (x - y) / (x+ y) depends on the direction.
1508        array(:)=zero
1509        where (abs(rhor(:,1)) > tol12) array(:)=(2*rhor(:,2)-rhor(:,1))/rhor(:,1)
1510      end if
1511 !    Case nspden==4, some other computation to be done
1512    else if(nspden==4)then
1513      if(iitems==5)then ! Magnetization
1514        array(:)=sqrt(rhor(:,2)**2+rhor(:,3)**2+rhor(:,4)**2)
1515      else if(iitems==6)then ! zeta = relative magnetization
1516        array(:)=(sqrt(rhor(:,2)**2+rhor(:,3)**2+rhor(:,4)**2))/rhor(:,1)
1517      end if
1518    end if
1519 
1520 !  Zero all the absolute values that are lower than tol8, for portability reasons.
1521    do ifft = 1, nfft_
1522      if(abs(array(ifft))<tol8)array(ifft)=zero
1523    end do
1524 
1525 !  DEBUG
1526 !  write(std_out,*) ' iitems,array(1:2)=',iitems,array(1:2)
1527 !  ENDDEBUG
1528 
1529    do indsign=1,2 ! Find alternatively the maximum and the minimum
1530      iisign=3-2*indsign
1531 
1532      if (nfft_ > 1) then
1533 !      Initialize the two first values
1534        value1=array(istart + 1) ; value2=array(istart + 2)
1535        index1=1 ; index2=2
1536 
1537 !      Ordering, if needed
1538        if( iisign*(value2+tol12) > iisign*(value1)) then
1539          temp=value2 ; value2=value1 ; value1=temp
1540          index1=2 ; index2=1
1541        end if
1542 
1543 !      Integration, if relevant
1544        if(present(ucvol).and. indsign==1)then
1545          integrated(iitems) = array(istart + 1)+array(istart + 2)
1546        end if
1547      else
1548        value1 = zero; value2 = zero
1549        index1 = 0;    index2 = 0
1550      end if
1551 
1552 !    DEBUG
1553 !    write(std_out,*) ' value1,value2,index1,index2=',value1,value2,index1,index2
1554 !    ENDDEBUG
1555 
1556 !    Loop over all points
1557      do ifft = 3, nfft_
1558 
1559        temp=array(istart + ifft)
1560        if(present(ucvol).and. indsign==1)integrated(iitems) = integrated(iitems)+temp
1561 !      Compares it to the second value
1562        if( iisign*(temp+tol12) > iisign*value2 ) then
1563 !        Compare it to the first value
1564          if( iisign*(temp+tol12) > iisign*value1 ) then
1565            value2=value1 ; index2=index1
1566            value1=temp   ; index1=ifft
1567          else
1568            value2=temp   ; index2=ifft
1569          end if
1570        end if
1571 
1572      end do ! ifft
1573 
1574      value(1,indsign,iitems)=value1
1575      value(2,indsign,iitems)=value2
1576      iindex(1,indsign,iitems)=index1
1577      iindex(2,indsign,iitems)=index2
1578 
1579 !    DEBUG
1580 !    write(std_out,*) ' it,v1,i1=',iitems, value1,index1
1581 !    write(std_out,*) ' it,v2,i2=',iitems, value2,index2
1582 !    ENDDEBUG
1583 
1584    end do ! indsign
1585 
1586    if(present(ucvol))then
1587      nfftot=ngfft(1) * ngfft(2) * ngfft(3)
1588      integrated(iitems)=integrated(iitems)*ucvol/nfftot
1589    end if
1590 
1591 !  Integrate the array
1592 !  integrated(iitems)=zero
1593 !  do ifft=1,nfft_
1594 !  integrated(iitems) = integrated(iitems) + array(istart + ifft)
1595 !  enddo
1596 !  if(present(ucvol))integrated(iitems) = integrated(iitems)*ucvol/nfft_
1597 !  write(std_err,*)present(ucvol)
1598 !  if(present(ucvol))then
1599 !  write(std_err,*)ucvol
1600 !  endif
1601 
1602  end do ! iitems
1603 
1604  ABI_FREE(array)
1605 
1606 !-------------------------------------------------------------------
1607 !Enter section for FFT parallel case
1608 !if(mpi_enreg%paral_kgb>1) spaceComm=mpi_enreg%comm_fft; reduce=.true.
1609  spaceComm=mpi_enreg%comm_fft; reduce=.false.
1610  if(mpi_enreg%nproc_fft>1) then
1611    spaceComm=mpi_enreg%comm_fft; reduce=.true.
1612  else if(mpi_enreg%nproc_wvl>1) then
1613    spaceComm=mpi_enreg%comm_wvl; reduce=.true.
1614  end if
1615  nproc=xmpi_comm_size(spaceComm)
1616  me=xmpi_comm_rank(spaceComm)
1617 
1618  if (reduce) then
1619 
1620 !  Communicate all data to all processors with only two global communications
1621    ABI_MALLOC(value_fft,(5,nitems,nproc))
1622    ABI_MALLOC(index_fft,(2,2,nitems,nproc))
1623    value_fft(:,:,:)=zero
1624    index_fft(:,:,:,:)=0
1625    value_fft(1,:,me + 1)=value(1,1,:)
1626    value_fft(2,:,me + 1)=value(2,1,:)
1627    value_fft(3,:,me + 1)=value(1,2,:)
1628    value_fft(4,:,me + 1)=value(2,2,:)
1629    if(present(ucvol))value_fft(5,:,me + 1)=integrated(:)
1630    index_fft(:,:,:,me + 1)=iindex(:,:,:)
1631    call xmpi_sum(value_fft,spaceComm,ierr)
1632    call xmpi_sum(index_fft,spaceComm,ierr)
1633 
1634 !  Determine the global optimum and second optimum for each item
1635 !  Also, the integrated quantities, if relevant.
1636    do iitems=1,nitems
1637 
1638      if(present(ucvol))integrated(iitems)=sum(value_fft(5,iitems,1:nproc))
1639 
1640      do indsign=1,2 ! Find alternatively the maximum and the minimum
1641        iisign=3-2*indsign
1642 
1643 !      Initialisation
1644        value1=value_fft(2*indsign-1,iitems,1)
1645        value2=value_fft(2*indsign  ,iitems,1)
1646        index1=index_fft(1,indsign,iitems,1)
1647        index2=index_fft(2,indsign,iitems,1)
1648 
1649 !      Loop
1650        do iproc=1, nproc, 1
1651          do ii=1,2
1652            if(iproc>1 .or. ii==2)then
1653 
1654              temp=value_fft(ii+2*(indsign-1),iitems,iproc)
1655 !            Compares it to the second value
1656              if( iisign*(temp+tol12) > iisign*value2 ) then
1657 !              Compare it to the first value
1658                if( iisign*(temp+tol12) > iisign*value1 ) then
1659                  value2=value1 ; index2=index1
1660                  value1=temp   ; index1=index_fft(ii,indsign,iitems,iproc)
1661                else
1662                  value2=temp   ; index2=index_fft(ii,indsign,iitems,iproc)
1663                end if
1664              end if
1665 
1666            end if ! if(iproc>1 .or. ii==2)
1667          end do ! ii
1668        end do ! iproc
1669 
1670        value(1,indsign,iitems)=value1
1671        value(2,indsign,iitems)=value2
1672        iindex(1,indsign,iitems)=index1
1673        iindex(2,indsign,iitems)=index2
1674 
1675      end do ! iisign
1676    end do ! iitems
1677 
1678    ABI_FREE(value_fft)
1679    ABI_FREE(index_fft)
1680 
1681  end if !if(reduce)
1682 
1683 !-------------------------------------------------------------------
1684 
1685 !Determines the reduced coordinates of the min and max for each item
1686  ABI_MALLOC(coord,(3,2,2,nitems))
1687  do iitems=1,nitems
1688    do indsign=1,2
1689      do ii=1,2
1690        index1=iindex(ii,indsign,iitems)
1691        i3=(index1-1)/n1/n2
1692        i2=(index1-1-i3*n1*n2)/n1
1693        i1=index1-1-i3*n1*n2-i2*n1
1694        coord(1,ii,indsign,iitems)=dble(i1)/dble(n1)+tol12
1695        coord(2,ii,indsign,iitems)=dble(i2)/dble(n2)+tol12
1696        coord(3,ii,indsign,iitems)=dble(i3)/dble(n3)+tol12
1697 !      DEBUG
1698 !      write(std_out,*)' ii,indsign,iitems,coord(1:3)=',ii,indsign,iitems,coord(:,ii,indsign,iitems)
1699 !      write(std_out,*)' value ', value(ii, indsign, iitems)
1700 !      ENDDEBUG
1701      end do
1702    end do
1703  end do
1704 
1705 !-------------------------------------------------------------------------
1706 !Output
1707  if (mpi_enreg%paral_kgb==0.or.mpi_enreg%me_fft==0) then
1708    if(.true.)then
1709      do iitems=1,nitems
1710 
1711        if(ioptrhor==4 .and. iitems>2)exit
1712 
1713        select case (ioptrhor)
1714        case(0)
1715 
1716          if(iitems==1) write(message,'(a)')' Total charge density [el/Bohr^3]'
1717          if(nspden==2)then
1718            if(iitems==2) write(message,'(a)')' Spin up density      [el/Bohr^3]'
1719            if(iitems==3) write(message,'(a)')' Spin down density    [el/Bohr^3]'
1720            if(iitems==4) write(message,'(a)')' Magnetization (spin up - spin down) [el/Bohr^3]'
1721            if(iitems==5) write(message,'(a)')' Relative magnetization (=zeta, between -1 and 1)   '
1722          else if(nspden==4)then
1723            if(iitems==2) write(message,'(a)')' x component of magnetization [el/Bohr^3]'
1724            if(iitems==3) write(message,'(a)')' y component of magnetization [el/Bohr^3]'
1725            if(iitems==4) write(message,'(a)')' z component of magnetization [el/Bohr^3]'
1726            if(iitems==5) write(message,'(a)')' Magnetization (absolute value) [el/Bohr^3]'
1727            if(iitems==6) write(message,'(a)')' Relative magnetization (=zeta, between -1 and 1)   '
1728          end if
1729 
1730        case(1)
1731 
1732          if(iitems==1) write(message,'(a)')' Total kinetic energy density [Ha/Bohr^3]'
1733          if(nspden==2)then
1734            if(iitems==2) write(message,'(a)')' Spin up density      [Ha/Bohr^3]'
1735            if(iitems==3) write(message,'(a)')' Spin down density    [Ha/Bohr^3]'
1736            if(iitems==4) write(message,'(a)')' Magnetization (spin up - spin down) [Ha/Bohr^3]'
1737            if(iitems==5) write(message,'(a)')' Relative magnetization (=zeta, between -1 and 1)   '
1738          else if(nspden==4)then
1739            if(iitems==2) write(message,'(a)')' x component of magnetization [Ha/Bohr^3]'
1740            if(iitems==3) write(message,'(a)')' y component of magnetization [Ha/Bohr^3]'
1741            if(iitems==4) write(message,'(a)')' z component of magnetization [Ha/Bohr^3]'
1742            if(iitems==5) write(message,'(a)')' Magnetization (absolute value) [Ha/Bohr^3]'
1743            if(iitems==6) write(message,'(a)')' Relative magnetization (=zeta, between -1 and 1)   '
1744          end if
1745 
1746        case(2)
1747 
1748          if(iitems==1) write(message,'(a)')' Gradient of the electronic density [el/Bohr^4]'
1749          if(nspden==2)then
1750            if(iitems==2) write(message,'(a)')' Spin up density      [el/Bohr^4]'
1751            if(iitems==3) write(message,'(a)')' Spin down density    [el/Bohr^4]'
1752            if(iitems==4) write(message,'(a)')' Magnetization (spin up - spin down) [el/Bohr^4]'
1753            if(iitems==5) write(message,'(a)')' Relative magnetization (=zeta, between -1 and 1)   '
1754          else if(nspden==4)then
1755            if(iitems==2) write(message,'(a)')' x component of magnetization [el/Bohr^4]'
1756            if(iitems==3) write(message,'(a)')' y component of magnetization [el/Bohr^4]'
1757            if(iitems==4) write(message,'(a)')' z component of magnetization [el/Bohr^4]'
1758            if(iitems==5) write(message,'(a)')' Magnetization (absolute value) [el/Bohr^4]'
1759            if(iitems==6) write(message,'(a)')' Relative magnetization (=zeta, between -1 and 1)   '
1760          end if
1761 
1762        case(3)
1763 
1764          if(iitems==1) write(message,'(a)')' Laplacian of the electronic density [el/Bohr^5]'
1765          if(nspden==2)then
1766            if(iitems==2) write(message,'(a)')' Spin up density      [el/Bohr^5]'
1767            if(iitems==3) write(message,'(a)')' Spin down density    [el/Bohr^5]'
1768            if(iitems==4) write(message,'(a)')' Magnetization (spin up - spin down) [el/Bohr^5]'
1769            if(iitems==5) write(message,'(a)')' Relative magnetization (=zeta, between -1 and 1)   '
1770          else if(nspden==4)then
1771            if(iitems==2) write(message,'(a)')' x component of magnetization [el/Bohr^5]'
1772            if(iitems==3) write(message,'(a)')' y component of magnetization [el/Bohr^5]'
1773            if(iitems==4) write(message,'(a)')' z component of magnetization [el/Bohr^5]'
1774            if(iitems==5) write(message,'(a)')' Magnetization (absolute value) [el/Bohr^5]'
1775            if(iitems==6) write(message,'(a)')' Relative magnetization (=zeta, between -1 and 1)   '
1776          end if
1777 
1778        case(4)
1779 
1780          if(iitems==1) write(message,'(a)')' Electron Localization Function (ELF) [min:0;max:1]'
1781          if(nspden==2)then
1782            if(iitems==2) write(message,'(a)')' Spin up ELF      [min:0;max:1]'
1783 !            if(iitems==3) write(message,'(a)')' Spin down ELF    [min:0;max:1]'
1784 !            if(iitems==4) write(message,'(a)')' Magnetization (spin up - spin down) [el/Bohr^4]'
1785 !            if(iitems==5) write(message,'(a)')' Relative magnetization (=zeta, between -1 and 1)   '
1786          else if(nspden==4)then
1787 !            if(iitems==2) write(message,'(a)')' x component of magnetization [el/Bohr^4]'
1788 !            if(iitems==3) write(message,'(a)')' y component of magnetization [el/Bohr^4]'
1789 !            if(iitems==4) write(message,'(a)')' z component of magnetization [el/Bohr^4]'
1790 !            if(iitems==5) write(message,'(a)')' Magnetization (spin up - spin down) [el/Bohr^4]'
1791 !            if(iitems==6) write(message,'(a)')' Relative magnetization (=zeta, between -1 and 1)   '
1792          end if
1793        end select
1794 
1795        call wrtout(iout,message,'COLL')
1796 
1797        write(message,'(a,es13.4,a,3f10.4)')   ')     Maximum= ',&
1798 &       value(1,1,iitems),'  at reduced coord.',coord(:,1,1,iitems)
1799        call wrtout(iout,message,'COLL')
1800        if(option==2)then
1801          write(message,'(a,es13.4,a,3f10.4)') ')Next maximum= ',&
1802 &         value(2,1,iitems),'  at reduced coord.',coord(:,2,1,iitems)
1803          call wrtout(iout,message,'COLL')
1804        end if
1805        write(message,'(a,es13.4,a,3f10.4)')   ')     Minimum= ',&
1806 &       value(1,2,iitems),'  at reduced coord.',coord(:,1,2,iitems)
1807        call wrtout(iout,message,'COLL')
1808        if(option==2)then
1809          write(message,'(a,es13.4,a,3f10.4)') ')Next minimum= ',&
1810 &         value(2,2,iitems),'  at reduced coord.',coord(:,2,2,iitems)
1811          call wrtout(iout,message,'COLL')
1812        end if
1813        if(present(ucvol))then
1814          if(.not.(nspden==2.and.iitems==5) .and. .not.(nspden==4.and.iitems==6))then
1815            if(abs(integrated(iitems))<tol10)integrated(iitems)=zero
1816            write(message,'(a,es13.4)')'   Integrated= ',integrated(iitems)
1817            call wrtout(iout,message,'COLL')
1818          end if
1819        end if
1820 
1821      end do ! iitems
1822    end if
1823 
1824    if(.false.)then
1825 
1826      select case(optrhor)
1827      case(0)
1828        write(txt1_in_mssg, '(a)')" Min el dens="
1829        write(txt2_in_mssg, '(a)')" el/bohr^3 at reduced coord."
1830        write(txt3_in_mssg, '(a)')" Max el dens="
1831      case(1)
1832        write(txt1_in_mssg, '(a)')" Min kin energy dens="
1833        write(txt2_in_mssg, '(a)')" bohr^(-5) at reduced coord."
1834        write(txt3_in_mssg, '(a)')" Max kin energy dens="
1835      end select
1836 
1837      write(message, '(a,a,1p,e12.4,a,0p,3f8.4)' ) ch10,&
1838 &     trim(txt1_in_mssg),value(1,2,1),&
1839 &     trim(txt2_in_mssg),coord(:,1,2,1)
1840      call wrtout(iout,message,'COLL')
1841      if(option==2)then
1842        write(message, '(a,1p,e12.4,a,0p,3f8.4)' ) &
1843 &       ',   next min=',value(2,2,1),&
1844 &       trim(txt2_in_mssg),coord(:,2,2,1)
1845        call wrtout(iout,message,'COLL')
1846      end if
1847      write(message, '(a,1p,e12.4,a,0p,3f8.4)' )&
1848 &     trim(txt3_in_mssg),value(1,1,1),&
1849 &     trim(txt2_in_mssg),coord(:,1,1,1)
1850      call wrtout(iout,message,'COLL')
1851      if(option==2)then
1852        write(message, '(a,1p,e12.4,a,0p,3f8.4)' )&
1853 &       ',   next max=',value(2,1,1),&
1854 &       trim(txt2_in_mssg),coord(:,2,1,1)
1855        call wrtout(iout,message,'COLL')
1856      end if
1857 
1858      if(nspden>=2)then
1859        write(message, '(a,a,1p,e12.4,a,0p,3f8.4)' ) ch10,&
1860 &       ',Min spin pol zeta=',value(1,2,4+nspden/2),&
1861 &       ' at reduced coord.',coord(:,1,2,4+nspden/2)
1862        call wrtout(iout,message,'COLL')
1863        if(option==2)then
1864          write(message, '(a,1p,e12.4,a,0p,3f8.4)' )&
1865 &         ',         next min=',value(2,2,4+nspden/2),&
1866 &         ' at reduced coord.',coord(:,2,2,4+nspden/2)
1867          call wrtout(iout,message,'COLL')
1868        end if
1869        write(message, '(a,1p,e12.4,a,0p,3f8.4)' )&
1870 &       ',Max spin pol zeta=',value(1,1,4+nspden/2),&
1871 &       ' at reduced coord.',coord(:,1,1,4+nspden/2)
1872        call wrtout(iout,message,'COLL')
1873        if(option==2)then
1874          write(message, '(a,1p,e12.4,a,0p,3f8.4)' )&
1875 &         ',         next max=',value(2,1,4+nspden/2),&
1876 &         ' at reduced coord.',coord(:,2,1,4+nspden/2)
1877          call wrtout(iout,message,'COLL')
1878        end if
1879      end if ! nspden
1880 
1881    end if ! second section always true
1882 
1883    if(nspden==2 .and. .false.)then
1884      write(message,'(a)')&
1885 &     '                               Position in reduced coord.       (  x         y         z )'
1886      call wrtout(iout,message,'COLL')
1887      write(message,'(a,es13.4,a,3f10.4)')'      Minimum (Total  el-den) : [el/Bohr^3]',&
1888 &     rhomn1(1),'  at',ri_rhomn1(1,1),ri_rhomn1(2,1),ri_rhomn1(3,1)
1889      call wrtout(iout,message,'COLL')
1890      write(message,'(a,es13.4,a,3f10.4)')'      Minimum (Spin-up   den) : [el/Bohr^3]',&
1891 &     rhomn1(2),'  at',ri_rhomn1(1,2),ri_rhomn1(2,2),ri_rhomn1(3,2)
1892      call wrtout(iout,message,'COLL')
1893      write(message,'(a,es13.4,a,3f10.4)')'      Minimum (Spin-down den) : [el/Bohr^3]',&
1894 &     zetmn1(1),'  at',ri_zetmn1(1,1),ri_zetmn1(2,1),ri_zetmn1(3,1)
1895      call wrtout(iout,message,'COLL')
1896      write(message,'(a,es13.4,a,3f10.4)')'      Minimum (Spin pol zeta) :   [m/|m|]  ',&
1897 &     zetmn1(2),'  at',ri_zetmn1(1,2),ri_zetmn1(2,2),ri_zetmn1(3,2)
1898      call wrtout(iout,message,'COLL')
1899      if(option==2)then
1900        write(message,'(a,es13.4,a,3f10.4)')' Next minimum (Total  el-den) : [el/Bohr^3]',&
1901 &       rhomn2(1),'  at',ri_rhomn2(1,1),ri_rhomn2(2,1),ri_rhomn2(3,1)
1902        call wrtout(iout,message,'COLL')
1903        write(message,'(a,es13.4,a,3f10.4)')' Next minimum (Spin-up   den) : [el/Bohr^3]',&
1904 &       rhomn2(2),'  at',ri_rhomn2(1,2),ri_rhomn2(2,2),ri_rhomn2(3,2)
1905        call wrtout(iout,message,'COLL')
1906        write(message,'(a,es13.4,a,3f10.4)')' Next minimum (Spin-down den) : [el/Bohr^3]',&
1907 &       zetmn2(1),'  at',ri_zetmn2(1,1),ri_zetmn2(2,1),ri_zetmn2(3,1)
1908        call wrtout(iout,message,'COLL')
1909        write(message,'(a,es13.4,a,3f10.4)')' Next minimum (Spin pol zeta) :   [m/|m|]  ',&
1910 &       zetmn2(2),'  at',ri_zetmn2(1,2),ri_zetmn2(2,2),ri_zetmn2(3,2)
1911        call wrtout(iout,message,'COLL')
1912      end if
1913      write(message,*)' '
1914      call wrtout(iout,message,'COLL')
1915      write(message,'(a,es13.4,a,3f10.4)')'      Maximum (Total  el-den) : [el/Bohr^3]',&
1916 &     rhomx1(1),'  at',ri_rhomx1(1,1),ri_rhomx1(2,1),ri_rhomx1(3,1)
1917      call wrtout(iout,message,'COLL')
1918      write(message,'(a,es13.4,a,3f10.4)')'      Maximum (Spin-up   den) : [el/Bohr^3]',&
1919 &     rhomx1(2),'  at',ri_rhomx1(1,2),ri_rhomx1(2,2),ri_rhomx1(3,2)
1920      call wrtout(iout,message,'COLL')
1921      write(message,'(a,es13.4,a,3f10.4)')'      Maximum (Spin-down den) : [el/Bohr^3]',&
1922 &     zetmx1(1),'  at',ri_zetmx1(1,1),ri_zetmx1(2,1),ri_zetmx1(3,1)
1923      call wrtout(iout,message,'COLL')
1924      write(message,'(a,es13.4,a,3f10.4)')'      Maximum (Spin pol zeta) :   [m/|m|]  ',&
1925 &     zetmx1(2),'  at',ri_zetmx1(1,2),ri_zetmx1(2,2),ri_zetmx1(3,2)
1926      call wrtout(iout,message,'COLL')
1927      if(option==2)then
1928        write(message,'(a,es13.4,a,3f10.4)')' Next maximum (Total  el-den) : [el/Bohr^3]',&
1929 &       rhomx2(1),'  at',ri_rhomx2(1,1),ri_rhomx2(2,1),ri_rhomx2(3,1)
1930        call wrtout(iout,message,'COLL')
1931        write(message,'(a,es13.4,a,3f10.4)')' Next maximum (Spin-up   den) : [el/Bohr^3]',&
1932 &       rhomx2(2),'  at',ri_rhomx2(1,2),ri_rhomx2(2,2),ri_rhomx2(3,2)
1933        call wrtout(iout,message,'COLL')
1934        write(message,'(a,es13.4,a,3f10.4)')' Next maximum (Spin-down den) : [el/Bohr^3]',&
1935 &       zetmx2(1),'  at',ri_zetmx2(1,1),ri_zetmx2(2,1),ri_zetmx2(3,1)
1936        call wrtout(iout,message,'COLL')
1937        write(message,'(a,es13.4,a,3f10.4)')' Next maximum (Spin pol zeta) :   [m/|m|]  ',&
1938 &       zetmx2(2),'  at',ri_zetmx2(1,2),ri_zetmx2(2,2),ri_zetmx2(3,2)
1939        call wrtout(iout,message,'COLL')
1940      end if
1941    end if
1942 
1943    if(nspden==4 .and. .false.)then
1944      write(message,'(a)')&
1945 &     '                               Position in reduced coord.       (  x         y         z )'
1946      call wrtout(iout,message,'COLL')
1947      write(message,'(a,es13.4,a,3f10.4)')'      Minimum (Total  el-den) : [el/Bohr^3]',&
1948 &     rhomn1(1),'  at',ri_rhomn1(1,1),ri_rhomn1(2,1),ri_rhomn1(3,1)
1949      call wrtout(iout,message,'COLL')
1950      write(message,'(a,es13.4,a,3f10.4)')'      Minimum (Magnetizat.-x) :   [m/|m|]  ',&
1951 &     rhomn1(2),'  at',ri_rhomn1(1,2),ri_rhomn1(2,2),ri_rhomn1(3,2)
1952      call wrtout(iout,message,'COLL')
1953      write(message,'(a,es13.4,a,3f10.4)')'      Minimum (Magnetizat.-y) :   [m/|m|]  ',&
1954 &     rhomn1(3),'  at',ri_rhomn1(1,3),ri_rhomn1(2,3),ri_rhomn1(3,3)
1955      call wrtout(iout,message,'COLL')
1956      write(message,'(a,es13.4,a,3f10.4)')'      Minimum (Magnetizat.-z) :   [m/|m|]  ',&
1957 &     rhomn1(4),'  at',ri_rhomn1(1,4),ri_rhomn1(2,4),ri_rhomn1(3,4)
1958      call wrtout(iout,message,'COLL')
1959      write(message,'(a,es13.4,a,3f10.4)')'      Minimum (Spin pol zeta) :   [m/|m|]  ',&
1960 &     zetmn1(1),'  at',ri_zetmn1(1,1),ri_zetmn1(2,1),ri_zetmn1(3,1)
1961      call wrtout(iout,message,'COLL')
1962      if(option==2)then
1963        write(message,'(a,es13.4,a,3f10.4)')' Next-Minimum (Total  el-den) : [el/Bohr^3]',&
1964 &       rhomn2(1),'  at',ri_rhomn2(1,1),ri_rhomn2(2,1),ri_rhomn2(3,1)
1965        call wrtout(iout,message,'COLL')
1966        write(message,'(a,es13.4,a,3f10.4)')' Next-Minimum (Magnetizat.-x) :   [m/|m|]  ',&
1967 &       rhomn2(2),'  at',ri_rhomn2(1,2),ri_rhomn2(2,2),ri_rhomn2(3,2)
1968        call wrtout(iout,message,'COLL')
1969        write(message,'(a,es13.4,a,3f10.4)')' Next-Minimum (Magnetizat.-y) :   [m/|m|]  ',&
1970 &       rhomn2(3),'  at',ri_rhomn2(1,3),ri_rhomn2(2,3),ri_rhomn2(3,3)
1971        call wrtout(iout,message,'COLL')
1972        write(message,'(a,es13.4,a,3f10.4)')' Next-Minimum (Magnetizat.-z) :   [m/|m|]  ',&
1973 &       rhomn2(4),'  at',ri_rhomn2(1,4),ri_rhomn2(2,4),ri_rhomn2(3,4)
1974        call wrtout(iout,message,'COLL')
1975        write(message,'(a,es13.4,a,3f10.4)')' Next-Minimum (Spin pol zeta) :   [m/|m|]  ',&
1976 &       zetmn2(1),'  at',ri_zetmn2(1,1),ri_zetmn2(2,1),ri_zetmn2(3,1)
1977        call wrtout(iout,message,'COLL')
1978      end if
1979      write(message,*)' '
1980      call wrtout(iout,message,'COLL')
1981      write(message,'(a,es13.4,a,3f10.4)')'      Maximum (Total  el-den) : [el/Bohr^3]',&
1982 &     rhomx1(1),'  at',ri_rhomx1(1,1),ri_rhomx1(2,1),ri_rhomx1(3,1)
1983      call wrtout(iout,message,'COLL')
1984      write(message,'(a,es13.4,a,3f10.4)')'      Maximum (Magnetizat.-x) :   [m/|m|]  ',&
1985 &     rhomx1(2),'  at',ri_rhomx1(1,2),ri_rhomx1(2,2),ri_rhomx1(3,2)
1986      call wrtout(iout,message,'COLL')
1987      write(message,'(a,es13.4,a,3f10.4)')'      Maximum (Magnetizat.-y) :   [m/|m|]  ',&
1988 &     rhomx1(3),'  at',ri_rhomx1(1,3),ri_rhomx1(2,3),ri_rhomx1(3,3)
1989      call wrtout(iout,message,'COLL')
1990      write(message,'(a,es13.4,a,3f10.4)')'      Maximum (Magnetizat.-z) :   [m/|m|]  ',&
1991 &     rhomx1(4),'  at',ri_rhomx1(1,4),ri_rhomx1(2,4),ri_rhomx1(3,4)
1992      call wrtout(iout,message,'COLL')
1993      write(message,'(a,es13.4,a,3f10.4)')'      Maximum (Spin pol zeta) :   [m/|m|]  ',&
1994 &     zetmx1(1),'  at',ri_zetmx1(1,1),ri_zetmx1(2,1),ri_zetmx1(3,1)
1995      call wrtout(iout,message,'COLL')
1996      if(option==2)then
1997        write(message,'(a,es13.4,a,3f10.4)')' Next-Maximum (Total  el-den) : [el/Bohr^3]',&
1998 &       rhomx2(1),'  at',ri_rhomx2(1,1),ri_rhomx2(2,1),ri_rhomx2(3,1)
1999        call wrtout(iout,message,'COLL')
2000        write(message,'(a,es13.4,a,3f10.4)')' Next-Maximum (Magnetizat.-x) :   [m/|m|]  ',&
2001 &       rhomx2(2),'  at',ri_rhomx2(1,2),ri_rhomx2(2,2),ri_rhomx2(3,2)
2002        call wrtout(iout,message,'COLL')
2003        write(message,'(a,es13.4,a,3f10.4)')' Next-Maximum (Magnetizat.-y) :   [m/|m|]  ',&
2004 &       rhomx2(3),'  at',ri_rhomx2(1,3),ri_rhomx2(2,3),ri_rhomx2(3,3)
2005        call wrtout(iout,message,'COLL')
2006        write(message,'(a,es13.4,a,3f10.4)')' Next-Maximum (Magnetizat.-z) :   [m/|m|]  ',&
2007 &       rhomx2(4),'  at',ri_rhomx2(1,4),ri_rhomx2(2,4),ri_rhomx2(3,4)
2008        call wrtout(iout,message,'COLL')
2009        write(message,'(a,es13.4,a,3f10.4)')' Next-Maximum (Spin pol zeta) :   [m/|m|]  ',&
2010 &       zetmx2(1),'  at',ri_zetmx2(1,1),ri_zetmx2(2,1),ri_zetmx2(3,1)
2011        call wrtout(iout,message,'COLL')
2012      end if
2013    end if
2014  end if
2015 
2016  ABI_FREE(coord)
2017  ABI_FREE(value)
2018  ABI_FREE(iindex)
2019  ABI_FREE(integrated)
2020 
2021 end subroutine prtrhomxmn

m_mkrho/read_atomden [ Functions ]

[ Top ] [ m_mkrho ] [ Functions ]

NAME

 read_atomden

FUNCTION

INPUTS

 natom : number of atoms in cell
 nfft=(effective) number of FFT grid points (for this processor) - fine grid
 ngfft(18)=contain all needed information about 3D FFT,
 nspden : number of spin densities
 ntypat : number of types of atoms in the cell
 typat(natom) : list of atom types

OUTPUT

 rhor_atm(nfft,nspden) : full electron density on the (fine) grid

SOURCE

2043 subroutine read_atomden(MPI_enreg,natom,nfft,ngfft,nspden,ntypat, &
2044 &                       rhor_atm,typat,rprimd,xred,prtvol,file_prefix)
2045 
2046 !Arguments ------------------------------------
2047 !scalars
2048  integer,intent(in) :: natom,nfft,nspden,ntypat,prtvol
2049 !arrays
2050  type(MPI_type),intent(in) :: MPI_enreg
2051  integer,intent(in) :: ngfft(18),typat(natom)
2052  real(dp), intent(in) :: rprimd(3,3),xred(3,natom)
2053  real(dp),intent(inout) :: rhor_atm(nfft,nspden)
2054  character(len=7), intent(in) :: file_prefix
2055 
2056 !Local variables-------------------------------
2057 !scalars
2058  character(len=500) :: message
2059  character(len=120) :: filename
2060  character(len=7) :: calctype='replace'
2061  integer :: igrid,i,i1,i2,i3,io_err,itypat,unt
2062  integer :: natomgrmax,nlines,ngrid,n1,n2,n3
2063  real(dp) :: difx,dify,difz,ucvol!,norm
2064 !arrays
2065  integer :: natomgr(ntypat)
2066  real(dp) :: a(3),b(3),c(3)
2067  real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3)
2068  real(dp),allocatable :: atomrgrid(:,:),r_vec_grid(:,:),density(:,:)
2069  real(dp),allocatable :: rho(:)
2070 
2071 ! ************************************************************************
2072 
2073 !Initialise various variables
2074  ngrid = nfft
2075  a(:) = rprimd(:,1)
2076  b(:) = rprimd(:,2)
2077  c(:) = rprimd(:,3)
2078  ABI_MALLOC(rho,(ngrid))
2079  if (nspden/=1) then
2080    ABI_ERROR('read_atomden: Only nspden=1 allowed.')
2081  end if
2082  rho = rhor_atm(:,1)
2083  gmet=zero;gprimd=zero;rmet=zero;ucvol=zero
2084 
2085 
2086 !Calculate the r vector (reduced coord.) of the fine gridpoints
2087  ABI_MALLOC(r_vec_grid,(3,ngrid))
2088  igrid = 0
2089  n1 = ngfft(1)
2090  n2 = ngfft(2)
2091  n3 = ngfft(3)
2092  do i3=0,n3-1
2093    difz=dble(i3)/dble(n3)
2094    do i2=0,n2-1
2095      dify=dble(i2)/dble(n2)
2096      do i1=0,n1-1
2097        difx=dble(i1)/dble(n1)
2098        igrid = igrid + 1
2099        r_vec_grid(1,igrid)=difx*rprimd(1,1)+dify*rprimd(1,2)+difz*rprimd(1,3)
2100        r_vec_grid(2,igrid)=difx*rprimd(2,1)+dify*rprimd(2,2)+difz*rprimd(2,3)
2101        r_vec_grid(3,igrid)=difx*rprimd(3,1)+dify*rprimd(3,2)+difz*rprimd(3,3)
2102      end do
2103    end do
2104  end do
2105  if (igrid/=ngrid) then
2106    ABI_ERROR('read_atomden: igrid not equal to ngrid')
2107  end if
2108 
2109 !Read in atomic density data for each atom type
2110 !first check how many datapoints are in each file
2111  do itypat=1,ntypat
2112    filename='';io_err=0;
2113    if (itypat>0)  write(filename,'(a,a,i1,a)') trim(file_prefix), '_density_atom_type',itypat,'.dat'
2114    if (itypat>10) write(filename,'(a,a,i2,a)') trim(file_prefix), '_density_atom_type',itypat,'.dat'
2115    if (open_file(filename, message, newunit=unt, status='old',action='read') /= 0) then
2116      write(std_out,*) 'ERROR in read_atomden: Could not open file: ',filename
2117      write(std_out,*) ' Current implementation requires this file to be present'
2118      write(std_out,*) ' for each type of atom.'
2119      write(std_out,*)trim(message)
2120      ABI_ERROR("Cannot continue")
2121    end if
2122 !  Check number of lines in file
2123    nlines = 1;io_err=0;
2124    do
2125      read(unt,*,iostat=io_err)
2126      if (io_err<0) exit
2127      nlines = nlines + 1
2128    end do
2129    close(unt)
2130    natomgr(itypat) = nlines - 2
2131  end do ! Atom type
2132 !Allocate arrays and read in data
2133  natomgrmax = maxval(natomgr)
2134  ABI_MALLOC(atomrgrid,(natomgrmax,ntypat))
2135  ABI_MALLOC(density,(natomgrmax,ntypat))
2136  atomrgrid = zero ; density = zero
2137  do itypat=1,ntypat
2138    filename='';io_err=0;
2139    if (itypat>0)  write(filename,'(a,a,i1,a)') trim(file_prefix), '_density_atom_type',itypat,'.dat'
2140    if (itypat>10) write(filename,'(a,a,i2,a)') trim(file_prefix), '_density_atom_type',itypat,'.dat'
2141    if (open_file(filename,message,newunit=unt,status='old',action='read') /= 0) then
2142      ABI_ERROR(message)
2143    end if
2144    read(unt,*) ! Skip comment line
2145    do i=1,natomgr(itypat)
2146      read(unt,*) atomrgrid(i,itypat),density(i,itypat)
2147    end do
2148    close(unt)
2149    if (atomrgrid(1,itypat)/=zero) then
2150      write(std_out,*) 'ERROR in read_atomden, in file: ',filename
2151      write(std_out,*) ' First gridpoint has to be the origin.'
2152      ABI_ERROR("Cannot continue")
2153    end if
2154  end do ! Atom type
2155 
2156 !write(std_out,*) '*** --- In read_atomden before call--- ***'
2157 !write(std_out,*) '  calctype:',calctype,' natom:',natom
2158 !write(std_out,*) '    ntypat:',ntypat,' typat:',typat
2159 !write(std_out,*) '     ngrid:',ngrid
2160 !write(std_out,*) '         a:',a
2161 !write(std_out,*) '         b:',b
2162 !write(std_out,*) '         c:',c
2163 !write(std_out,*) '      xred:',xred
2164 !write(std_out,*) '   natomgr:',natomgr
2165 !write(std_out,*) 'natomgrmax:',natomgrmax
2166 !write(std_out,*) ' atomrgrid:',atomrgrid
2167 !write(std_out,*) '   density:',density
2168 !write(std_out,*) 'r_vec_grid:'
2169 !write(std_out,*) r_vec_grid
2170 
2171 !Call atomden
2172  call atomden(MPI_enreg,natom,ntypat,typat,ngrid,r_vec_grid,rho,a,b,c,xred, &
2173 & natomgr,natomgrmax,atomrgrid,density,prtvol,calctype)
2174 
2175 !if (prtvol>9) then ! calculate norm
2176 !call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
2177 !norm = SUM(rho(:))*ucvol/dble(n1*n2*n3)
2178 !write(message,'(a,F8.4)') '  In read_atomden - NORM OF DENSITY: ',norm
2179 !call wrtout(std_out,message,'COLL')
2180 !end if
2181 
2182  rhor_atm(:,1) = rho
2183 
2184  ABI_SFREE(atomrgrid)
2185  ABI_SFREE(density)
2186  ABI_SFREE(r_vec_grid)
2187  ABI_SFREE(rho)
2188 
2189 end subroutine read_atomden