TABLE OF CONTENTS


ABINIT/m_paw_mkrho [ Modules ]

[ Top ] [ Modules ]

NAME

  m_paw_mkrho

FUNCTION

  This module contains routines used to compute PAW density on the real space fine grid.

COPYRIGHT

 Copyright (C) 2018-2024 ABINIT group (MT, JWZ)
 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_paw_mkrho
23 
24  use defs_basis
25  use m_abicore
26  use m_errors
27  use m_xmpi
28 
29  use defs_abitypes,      only : MPI_type
30  use m_time,             only : timab
31  use m_pawang,           only : pawang_type
32  use m_pawrad,           only : pawrad_type,pawrad_deducer0
33  use m_pawtab,           only : pawtab_type,pawtab_get_lsize
34  use m_paw_sphharm,      only : initylmr
35  use m_pawfgrtab,        only : pawfgrtab_type,pawfgrtab_init,pawfgrtab_free
36  use m_pawrhoij,         only : pawrhoij_type,pawrhoij_copy,pawrhoij_free_unpacked, &
37 &                               pawrhoij_nullify,pawrhoij_free,pawrhoij_symrhoij
38  use m_pawfgr,           only : pawfgr_type
39  use m_paw_nhat,         only : pawmknhat,nhatgrid
40  use m_paral_atom,       only : get_my_atmtab,free_my_atmtab
41  use m_fourier_interpol, only : transgrid
42 
43  use m_sort,             only : sort_dp
44  use m_splines,          only : spline,splint
45  use m_io_tools,         only : open_file
46  use m_geometry,         only : xred2xcart
47  use m_pptools,          only : printxsf
48  use m_fft,              only : fourdp
49 
50  implicit none
51 
52  private
53 
54 !public procedures.
55  public :: pawmkrho ! Build PAW electronic density on fine grid, including compensation charge density
56  public :: denfgr   ! Build complete PAW electronic density on fine grid, including on-site contributions
57 
58 CONTAINS  !========================================================================================

m_paw_mkrho/denfgr [ Functions ]

[ Top ] [ m_paw_mkrho ] [ Functions ]

NAME

 denfgr

FUNCTION

  Construct complete electron density on fine grid, by removing nhat
  and adding PAW corrections

INPUTS

   atindx1(natom)=index table for atoms, inverse of atindx (see gstate.f)
   gmet(3,3)=reciprocal space metric tensor in bohr**-2.
   mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
   comm_atom=--optional-- MPI communicator over atoms
   my_natom=number of atoms treated by current processor
   natom= number of atoms in cell
   nattyp(ntypat)= # atoms of each type.
   ngfft(18)=contain all needed information about 3D FFT (see NOTES at beginning of scfcv)
   nhat(pawfgr%nfft,nspden)= compensation charge density used in PAW
   nspinor=Number of spinor components
   nsppol=Number of independent spin components.
   nspden= number of spin densities
   ntypat= number of types of atoms in the cell
   pawfgr <type(pawfgr_type)>= data about the fine grid
   pawrad(ntypat) <type(pawrad_type)>= radial mesh data for each type of atom
   pawrhoij(natom) <type(pawrhoij_type)>= rho_ij data for each atom
   pawtab(ntypat) <type(pawtab_type)>= PAW functions around each type of atom
   rhor(pawfgr%nfft,nspden)= input density ($\tilde{n}+\hat{n}$ in PAW case)
   rprimd(3,3)=dimensional primitive translations for real space (bohr)
   typat(natom)= list of atom types
   ucvol=unit cell volume (bohr**3)
   xred(3,natom)=reduced dimensionless atomic coordinates

OUTPUT

 rhor_paw(pawfgr%nfft,nspden)= full electron density on the fine grid

NOTES

   In PAW calculations, the valence density present in rhor includes the
   compensation charge density $\hat{n}$, and also doesn't include the on-site
   PAW contributions. For post-processing and proper visualization it is necessary
   to use the full electronic density, which is what this subroutine constructs.
   Specifically, it removes $\hat{n}$ from rhor, and also computes the on-site PAW
   terms. This is nothing other than the proper PAW treatment of the density
   operator $|\mathbf{r}\rangle\langle\mathbf{r}|$, and yields the formula
   $$\tilde{n}+\sum_{ij}\rho_ij\left[\varphi_i(\mathbf{r})\varphi_j(\mathbf{r})-
   \tilde{\varphi}_i(\mathbf{r})\tilde{\varphi}_j(\mathbf{r})\right]$$
   Notice that this formula is expressed on the fine grid, and requires
   interpolating the PAW radial functions onto this grid, as well as calling
   initylmr in order to get the angular functions on the grid points.

SOURCE

332  subroutine denfgr(atindx1,gmet,spaceComm_in,my_natom,natom,nattyp,ngfft,nhat,nspinor,nsppol,nspden,ntypat, &
333 & pawfgr,pawrad,pawrhoij,pawtab,prtvol,rhor,rhor_paw,rhor_n_one,rhor_nt_one,rprimd,typat,ucvol,xred,&
334 & abs_n_tilde_nt_diff,znucl,mpi_atmtab,comm_atom) ! Optional arguments
335 
336 !Arguments ------------------------------------
337 !scalars
338  integer,intent(in) :: my_natom,natom,nspden,ntypat,prtvol,nsppol,nspinor
339  integer,optional,intent(in) :: comm_atom
340  real(dp),intent(in) :: ucvol
341  type(pawfgr_type),intent(in) :: pawfgr
342 !arrays
343  integer,intent(in) :: spaceComm_in
344  integer,intent(in) :: atindx1(natom),nattyp(ntypat),ngfft(18),typat(natom)
345  integer,optional,target,intent(in) :: mpi_atmtab(:)
346  real(dp),intent(in) :: gmet(3,3),nhat(pawfgr%nfft,nspden)
347  real(dp),intent(in) :: rhor(pawfgr%nfft,nspden),rprimd(3,3)
348  real(dp),intent(inout) :: xred(3,natom)
349  real(dp),intent(out) :: rhor_paw(pawfgr%nfft,nspden)
350  real(dp),intent(out) :: rhor_n_one(pawfgr%nfft,nspden)
351  real(dp),intent(out) :: rhor_nt_one(pawfgr%nfft,nspden)
352  real(dp),optional,intent(out) :: abs_n_tilde_nt_diff(nspden)
353  real(dp),optional,intent(in) :: znucl(ntypat)
354  type(pawrad_type),intent(in) :: pawrad(ntypat)
355  type(pawrhoij_type),intent(in) :: pawrhoij(my_natom)
356  type(pawtab_type),target,intent(in) :: pawtab(ntypat)
357 
358 !Local variables-------------------------------
359 !scalars
360  integer,parameter :: master=0
361  integer :: delta,iatom,ierr,ifgd,ifftsph,inl,inrm,ipsang,irhoij
362  integer :: ispden,itypat,il,im,ilm,iln,ilmn
363  integer :: jl,jlm,jln,jm,j0lmn,jlmn
364  integer :: klmn,my_comm_atom,my_start_indx,my_end_indx
365  integer :: nfgd,nnl,normchoice,nprocs,optcut,optgr0,optgr1,optgr2
366  integer :: optrad,option,my_rank,remainder,tmp_unt
367  real(dp) :: phj,phi,rR,tphj,tphi,ybcbeg,ybcend
368  logical :: my_atmtab_allocated,paral_atom
369  character(len=500) :: message
370 !arrays
371  integer,allocatable :: l_size_atm(:),nrm_ifftsph(:)
372  integer,ABI_CONTIGUOUS pointer :: indlmn(:,:)
373  integer,pointer :: my_atmtab(:)
374  real(dp) :: ylmgr(3,3,0)
375  real(dp) :: yvals(4),xcart(3,natom)
376  real(dp),allocatable :: diag(:),nrm(:),phigrd(:,:),tphigrd(:,:),ylm(:,:),ypp(:)
377  real(dp),allocatable :: phi_at_zero(:),tphi_at_zero(:)
378  real(dp),allocatable :: rhor_tmp(:,:),tot_rhor(:)
379  character(len=fnlen) :: xsf_fname
380  type(pawfgrtab_type) :: local_pawfgrtab(my_natom)
381 
382 ! ************************************************************************
383 
384  DBG_ENTER("COLL")
385 
386  if (my_natom>0) then
387    ABI_CHECK(pawrhoij(1)%qphase==1,'denfgr not supposed to be called with qphase/=1!')
388  end if
389 
390 !Set up parallelism over atoms (compatible only with band-FFT parallelism)
391  paral_atom=(present(comm_atom).and.(my_natom/=natom))
392  nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
393  my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
394  call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,&
395 & my_natom_ref=my_natom)
396 
397 !MG: FIXME It won't work if atom-parallelism is used
398 !but even the loop over atoms below should be rewritten in this case.
399 
400 !use a local copy of pawfgrtab to make sure we use the correction in the paw spheres
401 !the usual pawfgrtab uses r_shape which may not be the same as r_paw
402  if (my_natom>0) then
403    if (paral_atom) then
404      call pawtab_get_lsize(pawtab,l_size_atm,my_natom,typat,mpi_atmtab=my_atmtab)
405      call pawfgrtab_init(local_pawfgrtab,pawrhoij(1)%qphase,l_size_atm,nspden,typat,&
406 &     mpi_atmtab=my_atmtab,comm_atom=my_comm_atom)
407    else
408      call pawtab_get_lsize(pawtab,l_size_atm,my_natom,typat)
409      call pawfgrtab_init(local_pawfgrtab,pawrhoij(1)%qphase,l_size_atm,nspden,typat)
410    end if
411    ABI_FREE(l_size_atm)
412  end if
413 
414 !Note: call to nhatgrid: comm_fft not used because FFT parallelism
415 !is done manually below
416  optcut = 1 ! use rpaw to construct local_pawfgrtab
417  optgr0 = 0; optgr1 = 0; optgr2 = 0 ! dont need gY terms locally
418  optrad = 1 ! do store r-R
419  if (paral_atom) then
420    call nhatgrid(atindx1,gmet,my_natom,natom,nattyp,ngfft,ntypat,&
421 &   optcut,optgr0,optgr1,optgr2,optrad,local_pawfgrtab,pawtab,rprimd,typat,ucvol,xred,&
422 &   comm_atom=my_comm_atom,mpi_atmtab=my_atmtab)
423  else
424    call nhatgrid(atindx1,gmet,my_natom,natom,nattyp,ngfft,ntypat,&
425 &   optcut,optgr0,optgr1,optgr2,optrad,local_pawfgrtab,pawtab,rprimd,typat,ucvol,xred)
426  end if
427 !now local_pawfgrtab is ready to use
428 
429 !Initialise output arrays.
430  rhor_paw=zero; rhor_n_one=zero; rhor_nt_one=zero
431 
432 !Initialise and check parallell execution
433  my_rank = xmpi_comm_rank(spaceComm_in)
434  nprocs = xmpi_comm_size(spaceComm_in)
435 
436 
437 !loop over atoms in cell
438  do iatom = 1, my_natom
439    itypat = pawrhoij(iatom)%itypat
440    indlmn => pawtab(itypat)%indlmn
441    nfgd = local_pawfgrtab(iatom)%nfgd ! number of points in the fine grid for this PAW sphere
442    nnl = pawtab(itypat)%basis_size ! number of nl elements in PAW basis
443 
444 !  Division of fine grid points among processors
445    if (nprocs==1) then ! Make sure everything runs with one proc
446      write(message,'(a)') '  In denfgr - number of processors:     1'
447      call wrtout(std_out,message,'COLL')
448      write(message,'(a)') '  Calculation of PAW density done in serial'
449      call wrtout(std_out,message,'COLL')
450      write(message,'(a,I6)') '  Number of fine grid points:',nfgd
451      call wrtout(std_out,message,'COLL')
452      my_start_indx = 1
453      my_end_indx = nfgd
454    else ! Divide up the fine grid points among the processors
455      write(message,'(a,I4)') '  In denfgr - number of processors: ',nprocs
456      call wrtout(std_out,message,'COLL')
457      write(message,'(a)') '  Calculation of PAW density done in parallel'
458      call wrtout(std_out,message,'COLL')
459      write(message,'(a,I6)') '  Number of fine grid points:',nfgd
460      call wrtout(std_out,message,'COLL')
461 !    Divide the fine grid points among the processors
462      delta = int(floor(real(nfgd)/real(nprocs)))
463      remainder = nfgd-nprocs*delta
464      my_start_indx = 1+my_rank*delta
465      my_end_indx = (my_rank+1)*delta
466 !    Divide the remainder points among the processors
467 !    by shuffling indices
468      if ((my_rank+1)>remainder) then
469        my_start_indx = my_start_indx + remainder
470        my_end_indx = my_end_indx + remainder
471      else
472        my_start_indx = my_start_indx + my_rank
473        my_end_indx = my_end_indx + my_rank + 1
474      end if
475      if (prtvol>9) then
476        write(message,'(a,I6)') '  My index Starts at: ',my_start_indx
477        call wrtout(std_out,message,'PERS')
478        write(message,'(a,I6)') '             Ends at: ',my_end_indx
479        call wrtout(std_out,message,'PERS')
480        write(message,'(a,I6)') '               # pts: ',my_end_indx+1-my_start_indx
481        call wrtout(std_out,message,'PERS')
482      end if
483    end if
484 
485    write(message,'(a,I3,a,I3)') '  Entered loop for atom: ',iatom,' of:',natom
486    call wrtout(std_out,message,'PERS')
487 
488 !  obtain |r-R| values on fine grid
489    ABI_MALLOC(nrm,(nfgd))
490    do ifgd=1, nfgd
491      nrm(ifgd) = sqrt(dot_product(local_pawfgrtab(iatom)%rfgd(:,ifgd),local_pawfgrtab(iatom)%rfgd(:,ifgd)))
492    end do ! these are the |r-R| values
493 
494 !  compute Ylm for each r-R vector.
495 !  ----
496    ipsang = 1 + (pawtab(itypat)%l_size - 1)/2 ! recall l_size=2*l_max+1
497    ABI_MALLOC(ylm,(ipsang*ipsang,nfgd))
498    option = 1 ! compute Ylm(r-R) for vectors
499    normchoice = 1 ! use computed norms of input vectors
500    call initylmr(ipsang,normchoice,nfgd,nrm,option,local_pawfgrtab(iatom)%rfgd,ylm,ylmgr)
501 
502 !  in order to do spline fits, the |r-R| data must be sorted
503 !  ----
504    ABI_MALLOC(nrm_ifftsph,(nfgd))
505    nrm_ifftsph(:) = local_pawfgrtab(iatom)%ifftsph(:) ! copy of indices of points, to be rearranged by sort_dp
506    call sort_dp(nfgd,nrm,nrm_ifftsph,tol8) ! sort the nrm points, keeping track of which goes where
507 
508 !  now make spline fits of phi and tphi  onto the fine grid around the atom
509 !  ----
510    ABI_MALLOC(phigrd,(nfgd,nnl))
511    ABI_MALLOC(tphigrd,(nfgd,nnl))
512    ABI_MALLOC(phi_at_zero,(nnl))
513    ABI_MALLOC(tphi_at_zero,(nnl))
514    ABI_MALLOC(ypp,(pawtab(itypat)%mesh_size))
515    ABI_MALLOC(diag,(pawtab(itypat)%mesh_size))
516 
517    do inl = 1, nnl
518 
519 !    spline phi onto points
520      ypp(:) = zero; diag(:) = zero; ybcbeg = zero; ybcend = zero;
521      call spline(pawrad(itypat)%rad,pawtab(itypat)%phi(:,inl),pawtab(itypat)%mesh_size,ybcbeg,ybcend,ypp)
522      call splint(pawtab(itypat)%mesh_size,pawrad(itypat)%rad,pawtab(itypat)%phi(:,inl),ypp,nfgd,nrm,phigrd(:,inl))
523 
524 !    next splint tphi onto points
525      ypp(:) = zero; diag(:) = zero; ybcbeg = zero; ybcend = zero;
526      call spline(pawrad(itypat)%rad,pawtab(itypat)%tphi(:,inl),pawtab(itypat)%mesh_size,ybcbeg,ybcend,ypp)
527      call splint(pawtab(itypat)%mesh_size,pawrad(itypat)%rad,pawtab(itypat)%tphi(:,inl),ypp,nfgd,nrm,tphigrd(:,inl))
528 
529 !    Find out the value of the basis function at zero using extrapolation
530      yvals = zero
531 !    Extrapolate only if this is an s-state (l=0)
532      if (indlmn(1,inl)==0) then
533        yvals(2:4) = pawtab(itypat)%phi(2:4,inl)/pawrad(itypat)%rad(2:4)
534        call pawrad_deducer0(yvals,4,pawrad(itypat))
535        write(std_out,*) 'phi_at_zero: ',yvals(1),' from:',yvals(2:4)
536      end if
537      phi_at_zero(inl) = yvals(1)
538 
539      yvals = zero
540 !    Extrapolate only if this is an s-state (l=0)
541      if (indlmn(1,inl)==0) then
542        yvals(2:4) = pawtab(itypat)%tphi(2:4,inl)/pawrad(itypat)%rad(2:4)
543        call pawrad_deducer0(yvals,4,pawrad(itypat))
544        write(std_out,*) 'tphi_at_zero: ',yvals(1),' from:',yvals(2:4)
545      end if
546      tphi_at_zero(inl) = yvals(1)
547 
548    end do ! end loop over nnl basis functions
549    ABI_FREE(ypp)
550    ABI_FREE(diag)
551 
552 !  loop over basis elements for this atom
553 !  because we have to store things like <phi|r'><r'|phi>-<tphi|r'><r'|tphi> at each point of the
554 !  fine grid, there is no integration, and hence no simplifications of the Y_lm's. That's why
555 !  we have to loop through the basis elements in exhaustive detail, rather than just a loop over
556 !  lmn2_size or something comparable.
557 !  ----
558    if (prtvol>9) then
559      write(message,'(a,I3)') '  Entering j-loop over basis elements for atom:',iatom
560      call wrtout(std_out,message,'PERS')
561    end if
562 
563    do jlmn=1,pawtab(itypat)%lmn_size
564 
565      if (prtvol>9) then
566        write(message,'(2(a,I3))') '  Element:',jlmn,' of:',pawtab(itypat)%lmn_size
567        call wrtout(std_out,message,'PERS')
568      end if
569 
570      jl=indlmn(1,jlmn)
571      jm=indlmn(2,jlmn)
572      jlm=indlmn(4,jlmn)
573      jln=indlmn(5,jlmn)
574      j0lmn=jlmn*(jlmn-1)/2
575 
576      if (prtvol>9) then
577        write(message,'(a,I3)') '  Entering i-loop for j:',jlmn
578        call wrtout(std_out,message,'PERS')
579      end if
580 
581      do ilmn=1,jlmn
582 
583        if (prtvol>9) then
584          write(message,'(2(a,I3))') '    Element:',ilmn,' of:',jlmn
585          call wrtout(std_out,message,'PERS')
586        end if
587 
588        il=indlmn(1,ilmn)
589        im=indlmn(2,ilmn)
590        iln=indlmn(5,ilmn)
591        ilm=indlmn(4,ilmn)
592        klmn=j0lmn+ilmn
593 
594        if (prtvol>9) then
595          write(message,'(a)') '    Entering loop over nonzero elems of rhoij'
596          call wrtout(std_out,message,'PERS')
597        end if
598 
599 !      Loop over non-zero elements of rhoij
600        do irhoij=1,pawrhoij(iatom)%nrhoijsel
601          if (klmn==pawrhoij(iatom)%rhoijselect(irhoij)) then ! rho_ij /= 0 for this klmn
602 
603            do ifgd=my_start_indx, my_end_indx ! loop over fine grid points in current PAW sphere
604              ifftsph = local_pawfgrtab(iatom)%ifftsph(ifgd) ! index of the point on the grid
605 
606 !            have to retrieve the spline point to use since these were sorted
607              do inrm=1, nfgd
608                if(nrm_ifftsph(inrm) == ifftsph) exit ! have found nrm point corresponding to nfgd point
609              end do ! now inrm is the index of the sorted nrm vector to use
610 
611 !            avoid division by zero
612              if(nrm(inrm) > zero) then
613                rR = nrm(inrm) ! value of |r-R| in the following
614 !              recall that <r|phi>=u(r)*Slm(r^)/r
615                phj  = phigrd(inrm,jln)*ylm(jlm,ifgd)/rR
616                phi  = phigrd(inrm,iln)*ylm(ilm,ifgd)/rR
617                tphj = tphigrd(inrm,jln)*ylm(jlm,ifgd)/rR
618                tphi = tphigrd(inrm,iln)*ylm(ilm,ifgd)/rR
619              else
620 !              use precalculated <r|phi>=u(r)*Slm(r^)/r at r=0
621                phj  = phi_at_zero(jln)*ylm(jlm,ifgd)
622                phi  = phi_at_zero(iln)*ylm(ilm,ifgd)
623                tphj = tphi_at_zero(jln)*ylm(jlm,ifgd)
624                tphi = tphi_at_zero(iln)*ylm(ilm,ifgd)
625              end if ! check if |r-R| = 0
626 
627              do ispden=1,nspden
628                if (pawrhoij(iatom)%cplex_rhoij == 1) then
629                  rhor_paw(ifftsph,ispden) = rhor_paw(ifftsph,ispden) + &
630 &                 pawtab(itypat)%dltij(klmn)*pawrhoij(iatom)%rhoijp(irhoij,ispden)*(phj*phi - tphj*tphi)
631 
632                  rhor_n_one(ifftsph,ispden) = rhor_n_one(ifftsph,ispden) + &
633 &                 pawtab(itypat)%dltij(klmn)*pawrhoij(iatom)%rhoijp(irhoij,ispden)*phj*phi
634 
635                  rhor_nt_one(ifftsph,ispden) = rhor_nt_one(ifftsph,ispden) + &
636 &                 pawtab(itypat)%dltij(klmn)*pawrhoij(iatom)%rhoijp(irhoij,ispden)*tphj*tphi
637                else
638                  rhor_paw(ifftsph,ispden) = rhor_paw(ifftsph,ispden) + &
639 &                 pawtab(itypat)%dltij(klmn)*pawrhoij(iatom)%rhoijp(2*irhoij-1,ispden)*(phj*phi - tphj*tphi)
640 
641                  rhor_n_one(ifftsph,ispden) = rhor_n_one(ifftsph,ispden) + &
642 &                 pawtab(itypat)%dltij(klmn)*pawrhoij(iatom)%rhoijp(2*irhoij-1,ispden)*phj*phi
643 
644                  rhor_nt_one(ifftsph,ispden) = rhor_nt_one(ifftsph,ispden) + &
645 &                 pawtab(itypat)%dltij(klmn)*pawrhoij(iatom)%rhoijp(2*irhoij-1,ispden)*tphj*tphi
646                end if ! end check on cplex rhoij
647 
648              end do ! end loop over nsdpen
649            end do ! end loop over nfgd
650          end if ! end selection on rhoij /= 0
651        end do ! end loop over non-zero rhoij
652      end do ! end loop over ilmn atomic basis states
653    end do ! end loop over jlmn atomic basis states
654 
655    ABI_FREE(nrm)
656    ABI_FREE(nrm_ifftsph)
657    ABI_FREE(phigrd)
658    ABI_FREE(tphigrd)
659    ABI_FREE(ylm)
660    ABI_FREE(phi_at_zero)
661    ABI_FREE(tphi_at_zero)
662  end do     ! Loop on atoms
663 
664 !MPI sum on each node the different contributions to the PAW densities.
665  call xmpi_sum(rhor_paw,spaceComm_in,ierr)
666  call xmpi_sum(rhor_n_one,spaceComm_in,ierr)
667  call xmpi_sum(rhor_nt_one,spaceComm_in,ierr)
668  if (paral_atom) then
669    call xmpi_sum(rhor_paw,my_comm_atom,ierr)
670    call xmpi_sum(rhor_n_one,my_comm_atom,ierr)
671    call xmpi_sum(rhor_nt_one,my_comm_atom,ierr)
672  end if
673 
674  call wrtout(std_out,' *** Partial contributions to PAW rhor summed ***','PERS')
675  call xmpi_barrier(spaceComm_in)
676 
677 !Add the plane-wave contribution \tilde{n} and remove \hat{n}
678 !BE careful here since the storage mode of rhoij and rhor is different.
679  select case (nspinor)
680  case (1)
681    if (nsppol==1)  then
682      rhor_paw = rhor_paw + rhor - nhat
683    else  ! Spin-polarised case: rhor_paw contains rhor_paw(spin_up,spin_down) but we need rhor_paw(total,spin_up)
684      ABI_MALLOC(tot_rhor,(pawfgr%nfft))
685 !
686 !      AE rhor
687      tot_rhor(:) = SUM(rhor_paw,DIM=2)
688      rhor_paw(:,2) = rhor_paw(:,1)
689      rhor_paw(:,1) = tot_rhor
690      rhor_paw = rhor_paw + rhor - nhat
691 !
692 !      onsite AE rhor
693      tot_rhor(:) = SUM(rhor_n_one,DIM=2)
694      rhor_n_one(:,2) = rhor_n_one(:,1)
695      rhor_n_one(:,1) = tot_rhor
696 !
697 !      onsite PS rhor
698      tot_rhor(:) = SUM(rhor_nt_one,DIM=2)
699      rhor_nt_one(:,2) = rhor_nt_one(:,1)
700      rhor_nt_one(:,1) = tot_rhor
701 
702      ABI_FREE(tot_rhor)
703    end if
704 
705  case (2)
706 !    * if nspden==4, rhor contains (n^11, n^22, Re[n^12], Im[n^12].
707 !    Storage mode for rhoij is different, See pawaccrhoij.
708    ABI_ERROR("nspinor 2 not coded")
709  case default
710    write(message,'(a,i0)')" Wrong value for nspinor=",nspinor
711    ABI_ERROR(message)
712  end select
713 
714 !if (prtvol>9) then ! Check normalisation
715 !write(message,'(a,F8.4)') '  PAWDEN - NORM OF DENSITY: ',SUM(rhor_paw(:,1))*ucvol/PRODUCT(pawfgr%ngfft(1:3))
716 !call wrtout(std_out,message,'COLL')
717 !end if
718 
719  if (present(abs_n_tilde_nt_diff).AND.present(znucl)) then
720    ABI_MALLOC(rhor_tmp,(pawfgr%nfft,nspden))
721    do ispden=1,nspden
722      rhor_tmp(:,ispden) = zero
723      do iatom=1,my_natom
724        do ifgd=1,local_pawfgrtab(iatom)%nfgd ! loop over fine grid points in current PAW sphere
725          ifftsph = local_pawfgrtab(iatom)%ifftsph(ifgd) ! index of the point on the grid
726          rhor_tmp(ifftsph,ispden) = rhor(ifftsph,ispden) - nhat(ifftsph,ispden) &
727 &         - rhor_nt_one(ifftsph,ispden)
728        end do !ifgd
729      end do ! iatom
730    end do ! ispden
731    if (paral_atom) then
732      call xmpi_sum(rhor_tmp,my_comm_atom,ierr)
733    end if
734 
735    if (my_rank==master) then
736      do ispden=1,nspden
737 !      Write to xsf file
738        call xred2xcart(natom,rprimd,xcart,xred)
739        write(xsf_fname,'(a,I0,a)') 'N_tilde_onsite_diff_sp',ispden,'.xsf'
740        if (open_file(xsf_fname,message, unit=tmp_unt,status='unknown',form='formatted') /= 0) then
741          ABI_ERROR(message)
742        end if
743        call printxsf(ngfft(1),ngfft(2),ngfft(3),rhor_tmp(:,ispden),rprimd,&
744 &       (/zero,zero,zero/),natom,ntypat,typat,xcart,znucl,tmp_unt,0)
745        close(tmp_unt)
746        abs_n_tilde_nt_diff(ispden) = SUM(ABS(rhor_tmp(:,ispden)))/pawfgr%nfft
747        write(message,'(4(a),F16.9,2(a,I0),a)') ch10,'  Wrote xsf file with \tilde{n}-\tilde{n}^1.',ch10,&
748 &       '  Value of norm |\tilde{n}-\tilde{n}^1|:',&
749 &       abs_n_tilde_nt_diff(ispden),' spin: ',ispden,' of ',nspden,ch10
750        call wrtout(std_out,message,'COLL')
751      end do
752    end if
753    ABI_FREE(rhor_tmp)
754 
755  else if ((present(abs_n_tilde_nt_diff).AND.(.NOT.present(znucl))) &
756 &   .OR.(.NOT.present(abs_n_tilde_nt_diff).AND.(present(znucl)))) then
757    write(message,'(a)') ' Both abs_n_tilde_nt_diff *and* znucl must be passed',ch10,&
758 &   'to denfgr for |\tilde{n}-\tilde{n}^1| norm evaluation.'
759    ABI_ERROR(message)
760  end if
761 
762  call pawfgrtab_free(local_pawfgrtab)
763 
764 !Destroy atom table used for parallelism
765  call free_my_atmtab(my_atmtab,my_atmtab_allocated)
766 
767  call xmpi_barrier(spaceComm_in)
768 
769  DBG_EXIT("COLL")
770 
771  end subroutine denfgr

m_paw_mkrho/pawmkrho [ Functions ]

[ Top ] [ m_paw_mkrho ] [ Functions ]

NAME

 pawmkrho

FUNCTION

 PAW only:
 Build total pseudo (compensated) density (\tild_rho + \hat_rho)
 Build compensation charge density (\hat_rho)
 Build occupation matrix (packed storage)

INPUTS

  compute_rhor_rhog: if 1: set the computation of rhor and rhog in addition to the compensating charge.
                     if 0: compute only the compensating charge
  cplex: if 1, real space 1-order functions on FFT grid are REAL, if 2, COMPLEX
         1 for GS calculations
  gprimd(3,3)=dimensional primitive translations for reciprocal space(bohr^-1).
  indsym(4,nsym,natom)=indirect indexing array for atom labels
  ipert=index of perturbation if pawrhoij is a pertubed rhoij
        no meaning for ground-state calculations (should be 0)
  idir=direction of atomic displacement (in case of atomic displ. perturb.)
  mpi_enreg=information about MPI parallelization
  my_natom=number of atoms treated by current processor
  natom=number of atoms in cell
  nspden=number of spin-density components
  nsym=number of symmetry elements in space group
  ntypat=number of types of atoms in unit cell.
  paral_kgb=option for (kpt,g vectors,bands) parallelism
  pawang <type(pawang_type)>=angular mesh discretization and related data
  pawang_sym <type(pawang_type)>=angular data used for symmetrization
                                 optional parameter only needed for RF calculations
  pawfgr <type(paw_fgr_type)>=fine rectangular grid parameters
  pawfgrtab(natom) <type(pawfgrtab_type)>=atomic data given on fine rectangular grid
  pawprtvol=control print volume and debugging output for PAW
  pawrhoij0(natom) <type(pawrhoij_type)>= GS paw rhoij occupancies and related data (used only if ipert>0)
                                          optional parameter only needed for RF calculations
  pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
  qphon(3)=wavevector of the phonon (RF only)
  rhopsg(2,pawfgr%nfftc)= pseudo density given on the coarse grid in reciprocal space
  rhopsr(pawfgr%nfftc,nspden)= pseudo density given on the coarse grid in real space
  rprimd(3,3)=real space primitive translations.
  symafm(nsym)=(anti)ferromagnetic part of symmetry operations
  symrec(3,3,nsym)=symmetries of group in terms of operations on
                   reciprocal space primitive translations
  typat(natom)=type for each atom
  ucvol=volume of the unit cell
  xred(3,natom)= reduced atomic coordinates

OUTPUT

  compch_fft=compensation charge inside spheres integrated over fine fft grid
  pawnhat(pawfgr%nfft,nspden)=compensation charge density on fine rectangular grid (optional argument)
  rhog(2,pawfgr%nfft)= compensated pseudo density given on the fine grid in reciprocal space
                       This output is optional
  rhor(pawfgr%nfft,nspden)= compensated pseudo density given on the fine grid in real space

SIDE EFFECTS

  pawrhoij(my_natom)= PAW occupancies
                   At input : values at previous step  in packed storage (pawrhoij()%rhoijp)
                   At output: values (symmetrized)     in packed storage (pawrhoij()%rhoijp)
  pawrhoij_unsym(:)= unsymmetrized PAW occupancies
                   At input : values (unsymmetrized) in unpacked storage (pawrhoij()%rhoij_)
                   At output: values in unpacked storage (pawrhoij()%rhoij_) are destroyed

NOTES

  pawrhoij and pawrhoij_unsym can be identical (refer to the same pawrhoij datastructure).
  They should be different only if pawrhoij is distributed over atomic sites
  (in that case pawrhoij_unsym should not be distributed over atomic sites).

SOURCE

132 subroutine pawmkrho(compute_rhor_rhog,compch_fft,cplex,gprimd,idir,indsym,ipert,mpi_enreg,&
133 &          my_natom,natom,nspden,nsym,ntypat,paral_kgb,pawang,pawfgr,pawfgrtab,pawprtvol,&
134 &          pawrhoij,pawrhoij_unsym,&
135 &          pawtab,qphon,rhopsg,rhopsr,rhor,rprimd,symafm,symrec,typat,ucvol,usewvl,xred,&
136 &          pawang_sym,pawnhat,pawnhatgr,pawrhoij0,rhog) ! optional arguments
137 
138 !Arguments ------------------------------------
139 !scalars
140  integer,intent(in) :: compute_rhor_rhog,cplex,idir,ipert,my_natom,natom,nspden,nsym,ntypat,paral_kgb,pawprtvol
141  integer,intent(in) :: usewvl
142  real(dp),intent(in) :: ucvol
143  real(dp),intent(out) :: compch_fft
144  type(MPI_type),intent(in) :: mpi_enreg
145  type(pawang_type),intent(in) :: pawang
146  type(pawang_type),intent(in),optional :: pawang_sym
147  type(pawfgr_type),intent(in) :: pawfgr
148 !arrays
149  integer,intent(in) :: indsym(4,nsym,natom)
150  integer,intent(in) :: symafm(nsym),symrec(3,3,nsym),typat(natom)
151  real(dp),intent(in) :: gprimd(3,3),qphon(3),rprimd(3,3),xred(3,natom)
152  real(dp),intent(inout),target,optional :: pawnhat(cplex*pawfgr%nfft,nspden) !vz_i
153  real(dp),intent(inout),target,optional :: pawnhatgr(:,:,:) !vz_i
154  real(dp),intent(inout) :: rhor(cplex*pawfgr%nfft,nspden*compute_rhor_rhog)
155  real(dp),intent(out),optional :: rhog(2,pawfgr%nfft*compute_rhor_rhog)
156  real(dp),intent(inout) :: rhopsg(2,pawfgr%nfftc*compute_rhor_rhog),rhopsr(cplex*pawfgr%nfftc,nspden*compute_rhor_rhog)
157  type(pawfgrtab_type),intent(inout) :: pawfgrtab(my_natom)
158  type(pawrhoij_type),intent(inout),target :: pawrhoij(:)
159  type(pawrhoij_type),intent(inout) :: pawrhoij_unsym(:)
160  type(pawrhoij_type),intent(in),target,optional :: pawrhoij0(my_natom)
161  type(pawtab_type),intent(in) :: pawtab(ntypat)
162 
163 !Local variables-------------------------------
164 !scalars
165  integer :: choice,ider,izero,option
166  character(len=500) :: msg
167 !arrays
168  real(dp) :: tsec(2)
169  real(dp),target :: rhodum(0,0,0)
170  real(dp),pointer :: pawnhat_ptr(:,:)
171  real(dp),pointer :: pawnhatgr_ptr(:,:,:)
172  type(pawrhoij_type),pointer :: pawrhoij_ptr(:),pawrhoij0_ptr(:)
173 
174 ! ***********************************************************************
175 
176  DBG_ENTER("COLL")
177 
178  call timab(556,1,tsec)
179 
180 !Compatibility tests
181  if (size(pawrhoij_unsym)>0) then
182    if (pawrhoij_unsym(1)%use_rhoij_==0) then
183      msg='  rhoij_ field must be allocated in pawrhoij_unsym !'
184      ABI_BUG(msg)
185    end if
186  end if
187  if (ipert>0.and.(.not.present(pawrhoij0))) then
188    msg='  pawrhoij0 must be present when ipert>0 !'
189    ABI_BUG(msg)
190  end if
191 
192 !Symetrize PAW occupation matrix and store it in packed storage
193  call timab(557,1,tsec)
194  option=1;choice=1
195  if (present(pawang_sym)) then
196    call pawrhoij_symrhoij(pawrhoij,pawrhoij_unsym,choice,gprimd,indsym,ipert,&
197 &       natom,nsym,ntypat,option,pawang_sym,pawprtvol,pawtab,rprimd,symafm,&
198 &       symrec,typat,comm_atom=mpi_enreg%comm_atom,mpi_atmtab=mpi_enreg%my_atmtab,&
199 &       qphon=qphon)
200  else
201    call pawrhoij_symrhoij(pawrhoij,pawrhoij_unsym,choice,gprimd,indsym,ipert,&
202 &       natom,nsym,ntypat,option,pawang,pawprtvol,pawtab,rprimd,symafm,&
203 &       symrec,typat,comm_atom=mpi_enreg%comm_atom,mpi_atmtab=mpi_enreg%my_atmtab,&
204 &       qphon=qphon)
205  end if
206  call pawrhoij_free_unpacked(pawrhoij_unsym)
207  call timab(557,2,tsec)
208 
209 !In somes cases (parallelism), has to distribute the PAW occupation matrix
210  if (size(pawrhoij)==natom.and.(my_natom/=natom)) then
211    ABI_MALLOC(pawrhoij_ptr,(my_natom))
212    call pawrhoij_nullify(pawrhoij_ptr)
213    call pawrhoij_copy(pawrhoij,pawrhoij_ptr,&
214 &   mpi_atmtab=mpi_enreg%my_atmtab,comm_atom=mpi_enreg%comm_atom, &
215 &   keep_cplex=.false.,keep_qphase=.false.,keep_itypat=.false.,keep_nspden=.false.)
216  else
217    pawrhoij_ptr=>pawrhoij
218  end if
219 
220 !Compute compensation charge density
221  ider=0;izero=0
222  if (present(pawnhat)) then
223    pawnhat_ptr => pawnhat
224  else
225    ABI_MALLOC(pawnhat_ptr,(pawfgr%nfft,nspden))
226  end if
227  if (present(pawnhatgr)) then
228    pawnhatgr_ptr => pawnhatgr
229  else
230    pawnhatgr_ptr => rhodum
231  end if
232  if (present(pawrhoij0)) then
233    pawrhoij0_ptr => pawrhoij0
234  else
235    pawrhoij0_ptr => pawrhoij_ptr
236  end if
237 
238  call pawmknhat(compch_fft,cplex,ider,idir,ipert,izero,gprimd,my_natom,natom,&
239 & pawfgr%nfft,pawfgr%ngfft,ider,nspden,ntypat,pawang,pawfgrtab,&
240 & pawnhatgr_ptr,pawnhat_ptr,pawrhoij_ptr,pawrhoij0_ptr,pawtab,qphon,rprimd,ucvol,usewvl,xred,&
241 & comm_atom=mpi_enreg%comm_atom,mpi_atmtab=mpi_enreg%my_atmtab,&
242 & comm_fft=mpi_enreg%comm_fft,paral_kgb=paral_kgb,me_g0=mpi_enreg%me_g0,&
243 & distribfft=mpi_enreg%distribfft,mpi_comm_wvl=mpi_enreg%comm_wvl)
244 
245  if (compute_rhor_rhog/=0) then
246 !  Transfer pseudo density from coarse grid to fine grid
247    if(usewvl==0) then
248      call transgrid(cplex,mpi_enreg,nspden,+1,1,0,paral_kgb,pawfgr,rhopsg,rhodum,rhopsr,rhor)
249    end if
250 
251 !  Add pseudo density and compensation charge density (on fine grid)
252    rhor(:,:)=rhor(:,:)+pawnhat_ptr(:,:)
253 
254 !  Compute compensated pseudo density in reciprocal space
255    if (present(rhog)) then
256      call fourdp(cplex,rhog,rhor(:,1),-1,mpi_enreg,pawfgr%nfft,1,pawfgr%ngfft,0)
257    end if
258  end if
259 
260 !Free temporary memory spaces
261  if (.not.present(pawnhat)) then
262    ABI_FREE(pawnhat_ptr)
263  end if
264  if (size(pawrhoij)==natom.and.(my_natom/=natom)) then
265    call pawrhoij_free(pawrhoij_ptr)
266    ABI_FREE(pawrhoij_ptr)
267  end if
268  nullify(pawnhat_ptr)
269  nullify(pawnhatgr_ptr)
270  nullify(pawrhoij_ptr)
271 
272  call timab(556,2,tsec)
273 
274  DBG_EXIT("COLL")
275 
276 end subroutine pawmkrho