TABLE OF CONTENTS
- ABINIT/m_epjdos
- m_epjdos/dens_in_sph
- m_epjdos/dos_calcnwrite
- m_epjdos/epjdos_free
- m_epjdos/epjdos_new
- m_epjdos/epjdos_t
- m_epjdos/fatbands_ncwrite
- m_epjdos/partial_dos_fractions
- m_epjdos/partial_dos_fractions_paw
- m_epjdos/prtfatbands
- m_epjdos/recip_ylm
- m_epjdos/sphericaldens
ABINIT/m_epjdos [ Modules ]
NAME
m_epjdos
FUNCTION
Tools for the computiation of electronic PJDOSes
COPYRIGHT
Copyright (C) 2008-2024 ABINIT group (MVer, XG, SM, MT, BAmadon, MG, MB) 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_epjdos 23 24 use defs_basis 25 use m_abicore 26 use m_xmpi 27 use m_errors 28 use m_htetra 29 use m_splines 30 use m_cgtools 31 use m_atomdata 32 use m_crystal 33 use m_ebands 34 use m_nctk 35 #ifdef HAVE_NETCDF 36 use netcdf 37 #endif 38 use m_hdr 39 use m_mpinfo 40 use m_sort 41 use m_dtset 42 43 use defs_abitypes, only : MPI_type 44 use defs_datatypes, only : ebands_t, pseudopotential_type 45 use m_occ, only : dos_hdr_write 46 use m_time, only : cwtime, timab 47 use m_io_tools, only : open_file 48 use m_numeric_tools, only : simpson, simpson_int 49 use m_fstrings, only : int2char4, strcat 50 use m_special_funcs, only : jlspline_t, jlspline_new, jlspline_free, jlspline_integral 51 use m_kpts, only : tetra_from_kptrlatt 52 use m_kg, only : ph1d3d, getph 53 use m_gsphere, only : getkpgnorm 54 use m_fftcore, only : sphereboundary 55 use m_fft, only : fftpac, fourwf, fourdp 56 use m_pawrad, only : pawrad_type, simp_gen 57 use m_pawtab, only : pawtab_type 58 use m_pawcprj, only : pawcprj_type, pawcprj_alloc, pawcprj_get, pawcprj_free 59 use m_initylmg, only : initylmg 60 61 implicit none 62 63 private
m_epjdos/dens_in_sph [ Functions ]
[ Top ] [ m_epjdos ] [ Functions ]
NAME
dens_in_sph
FUNCTION
Calculate integrated density in sphere around each atom
INPUTS
cg = wavefunction coefficitents in recip space gmet = metric in recip space istwfk = storage mode for cg coefficients kg_k = G vector indices natom = number of atoms mpi_enreg=information about MPI parallelization ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft npw_k = number of plane waves for this kpoint ph1d = phase factors for different atoms for all G vectors rmax(natom) = max radius to integrate to (in bohr)
OUTPUT
cmax = integrated density for each atom for a rmax-radius sphere WARNING cg should not be modified by fourwf.
SOURCE
1238 subroutine dens_in_sph(cmax,cg,gmet,istwfk,kg_k,natom,ngfft,mpi_enreg,npw_k,& 1239 & ph1d,rmax,ucvol) 1240 1241 !Arguments ------------------------------------ 1242 !scalars 1243 integer,intent(in) :: istwfk,natom,npw_k 1244 real(dp),intent(in) :: ucvol 1245 type(MPI_type),intent(in) :: mpi_enreg 1246 !arrays 1247 integer,intent(in) :: kg_k(3,npw_k),ngfft(18) 1248 real(dp),intent(in) :: gmet(3,3) 1249 real(dp),intent(in) :: ph1d(2,(2*ngfft(1)+1+2*ngfft(2)+1+2*ngfft(3)+1)*natom) 1250 real(dp),intent(in) :: rmax(natom) 1251 real(dp),intent(inout) :: cg(2,npw_k) 1252 real(dp),intent(out) :: cmax(natom) 1253 1254 !Local variables ------------------------- 1255 !scalars 1256 integer,parameter :: tim_fourwf=0 1257 integer :: cplex,i1,i2,i3,iatom,id1,id2,id3,ifft,mgfft,n1,n2,n3,n4,n5,n6,nfft,nfftot 1258 real(dp) :: cmaxr,g1,g2,g3,norm,weight 1259 !arrays 1260 integer :: ngfft_here(18) 1261 integer,allocatable :: garr(:,:),gbound(:,:) 1262 real(dp),allocatable :: denpot(:,:,:),fofgout(:,:),fofr(:,:,:,:),gnorm(:) 1263 real(dp),allocatable :: ph3d(:,:,:),phkxred(:,:),rhog(:,:),rhor(:) 1264 real(dp),allocatable :: sphrhog(:,:) 1265 1266 ! ********************************************************************* 1267 1268 n1=ngfft(1) 1269 n2=ngfft(2) 1270 n3=ngfft(3) 1271 n4=ngfft(4) 1272 n5=ngfft(5) 1273 n6=ngfft(6) 1274 nfftot = n1*n2*n3 1275 nfft=n1*n2*n3 1276 ngfft_here(:) = ngfft(:) 1277 !fourwf doesnt work with other options for mode 0 (fft G -> r) 1278 ngfft_here(7)=111 1279 ngfft_here(8)=256 1280 mgfft=maxval(ngfft_here(1:3)) 1281 1282 call sqnorm_g(norm,istwfk,npw_k,cg,mpi_enreg%me_g0,mpi_enreg%comm_fft) 1283 1284 if (abs(one-norm) > tol6) then 1285 write(std_out,'(a,f8.5)' ) ' dens_in_sph : this state is not normalized : norm=',norm 1286 end if 1287 1288 !----------------------------------------------------------------- 1289 !inverse FFT of wavefunction to real space => density in real space 1290 !----------------------------------------------------------------- 1291 ABI_MALLOC(gbound,(2*mgfft+8,2)) 1292 call sphereboundary(gbound,istwfk,kg_k,mgfft,npw_k) 1293 1294 weight = one 1295 cplex=1 1296 ABI_MALLOC(denpot,(cplex*n4,n5,n6)) 1297 denpot(:,:,:)=zero 1298 ABI_MALLOC(fofgout,(2,npw_k)) 1299 ABI_MALLOC(fofr,(2,n4,n5,n6)) 1300 call fourwf(cplex,denpot,cg,fofgout,fofr,gbound,gbound, & 1301 & istwfk,kg_k,kg_k,mgfft,mpi_enreg,1,ngfft_here,npw_k,& 1302 & npw_k,n4,n5,n6,1,tim_fourwf,weight,weight) 1303 ABI_FREE(fofgout) 1304 ABI_FREE(fofr) 1305 ABI_FREE(gbound) 1306 1307 norm = sum(denpot(:,:,:))/nfftot 1308 if (abs(one-norm) > tol6) then 1309 write(std_out,'(a,f8.5)') ' dens_in_sph : this state is not normalized in real space : norm=',norm 1310 end if 1311 1312 !----------------------------------------------------------------- 1313 !FFT of new density: we obtain n(G) in rhog(1,:) 1314 !----------------------------------------------------------------- 1315 1316 !Change the packing of the reciprocal space density 1317 ABI_MALLOC(rhor,(nfft)) 1318 call fftpac(1,mpi_enreg,1,n1,n2,n3,n4,n5,n6,ngfft,rhor,denpot,1) 1319 1320 ABI_MALLOC(rhog,(2,nfft)) 1321 call fourdp(1,rhog,rhor,-1,mpi_enreg,nfft,1,ngfft,0) 1322 1323 ABI_FREE(rhor) 1324 ABI_FREE(denpot) 1325 1326 do ifft=1,nfft 1327 rhog(:,ifft) = rhog(:,ifft) / ucvol 1328 end do 1329 1330 !----------------------------------------------------------------- 1331 !calculate norms of G vectors 1332 !----------------------------------------------------------------- 1333 1334 ABI_MALLOC(garr,(3,nfft)) 1335 ABI_MALLOC(gnorm,(nfft)) 1336 id3=ngfft(3)/2+2 ; id2=ngfft(2)/2+2 ; id1=ngfft(1)/2+2 1337 do i3=1,n3 1338 g3=i3-(i3/(id3))*ngfft(3)-one 1339 do i2=1,n2 1340 g2=i2-(i2/(id2))*ngfft(2)-one 1341 do i1=1,n1 1342 g1=i1-(i1/(id1))*ngfft(1)-one 1343 ifft=i1+(i2-1)*n1+(i3-1)*n1*n2 1344 garr(1,ifft)=nint(g1) 1345 garr(2,ifft)=nint(g2) 1346 garr(3,ifft)=nint(g3) 1347 gnorm(ifft)=sqrt(gmet(1,1)*g1*g1 + & 1348 & two*gmet(2,1)*g2*g1 + & 1349 & two*gmet(3,1)*g3*g1 + & 1350 & gmet(2,2)*g2*g2 + & 1351 & gmet(3,2)*g3*g2 + & 1352 & gmet(3,3)*g3*g3) 1353 end do 1354 end do 1355 end do 1356 1357 !----------------------------------------------------------------- 1358 !For each atom call sphericaldens to calculate 1359 !n(G) * 1/|G|^3 * int_0^2*\pi*r_{max}*|G| 4 \pi y^2 j_0 (y) dy 1360 !for all G vectors put into array sphrhog 1361 !scalar product of phase factors with spherically convoluted density 1362 !----------------------------------------------------------------- 1363 1364 !largest mem occupation = nfft * (2(sphrog) +2*1(ph3d) +3(garr) +2(rhog) +1(gnorm)) = nfft * 10 1365 ABI_MALLOC(sphrhog,(2,nfft)) 1366 ABI_MALLOC(phkxred,(2,natom)) 1367 phkxred(1,:)=one 1368 phkxred(2,:)=zero 1369 ABI_MALLOC(ph3d,(2,nfft,1)) 1370 1371 do iatom=1,natom 1372 1373 call sphericaldens(rhog,gnorm,nfft,rmax(iatom),sphrhog) 1374 ! ----------------------------------------------------------------- 1375 ! Compute the phases for the whole set of fft vectors 1376 ! ----------------------------------------------------------------- 1377 1378 call ph1d3d(iatom,iatom,garr,natom,natom,nfft,ngfft(1),ngfft(2),ngfft(3),phkxred,ph1d,ph3d) 1379 1380 ! For the phase factors, take the compex conjugate, before evaluating the scalar product 1381 do ifft=1,nfft 1382 ph3d(2,ifft,1)=-ph3d(2,ifft,1) 1383 end do 1384 cplex=2 1385 call dotprod_v(cplex,cmaxr,nfft,1,0,ph3d,sphrhog,mpi_enreg%comm_fft) 1386 cmax(iatom) = cmaxr 1387 ! write(std_out,'(a,i4,a,es14.6,a,es12.6)' )' dens_in_sph : At ', iatom, ' has ',cmaxr, ' el.s in a sphere of rad ', rmax 1388 end do 1389 1390 ABI_FREE(rhog) 1391 ABI_FREE(gnorm) 1392 ABI_FREE(garr) 1393 ABI_FREE(sphrhog) 1394 ABI_FREE(ph3d) 1395 ABI_FREE(phkxred) 1396 1397 end subroutine dens_in_sph
m_epjdos/dos_calcnwrite [ Functions ]
[ Top ] [ m_epjdos ] [ Functions ]
NAME
dos_calcnwrite
FUNCTION
calculate DOS and write results to file(s)
INPUTS
dos_fractions= projections of wavefunctions on each angular momentum Ylm which is the weight going into the DOS for an l-decomposed dos dos_fractions_m= same as dos_fractions, but m-decomposed not just l- dos_fractions_paw1= contribution to dos fractions from the PAW partial waves (phi) dos_fractions_pawt1= contribution to dos fractions from the PAW pseudo partial waves (phi_tild) dtset structured datatype, in particular one uses : kptrlatt(3,3)=lattice vectors for full kpoint grid nshiftk =number of kpoint grid shifts pawprtdos =option to output the individual contributions to the partial DOS (0, 1 or 2) shiftk(3,nshiftk)=kpoint shifts usepaw =option for PAW crystal<crystal_t>=Object defining the unit cell and its symmetries. ebands<ebands_t>=Band structure data. fermie=Fermi energy fildata=name of the DOS output file mbesslang=maximum angular momentum for Bessel function expansion prtdosm=option for the m-contributions to the partial DOS ndosfraction= number of types of DOS we are calculating, e.g. the number of l channels. Could be much more general, for other types of partial DOS paw_dos_flag= option for partial dos in PAW comm=MPI communicator.
OUTPUT
(no explicit output)
SOURCE
334 subroutine dos_calcnwrite(dos,dtset,crystal,ebands,fildata,comm) 335 336 !Arguments ------------------------------------ 337 !scalars 338 integer,intent(in) :: comm 339 character(len=*),intent(in) :: fildata 340 type(dataset_type),intent(in) :: dtset 341 type(crystal_t),intent(in) :: crystal 342 type(ebands_t),intent(in) :: ebands 343 type(epjdos_t),intent(in) :: dos 344 345 !Local variables------------------------------- 346 !scalars 347 integer,parameter :: bcorr0=0,master=0 348 integer :: iat,iband,iene,ikpt,isppol,natsph,natsph_extra,nkpt,nsppol,i1,i2 349 integer :: nene,prtdos,unitdos,ierr,prtdosm,paw_dos_flag,mbesslang,ndosfraction 350 integer :: my_rank,nprocs,cnt,ifrac,ii 351 real(dp),parameter :: dos_max=9999.9999_dp 352 real(dp) :: buffer,deltaene,enemax,enemin,integral_DOS,max_occ 353 real(dp) :: cpu,wall,gflops 354 logical :: bigDOS,iam_master 355 character(len=10) :: tag 356 character(len=500) :: frmt,frmt_extra,msg 357 type(htetra_t) :: tetra 358 !arrays 359 integer,allocatable :: unt_atsph(:) 360 real(dp) :: list_dp(3) 361 real(dp),allocatable :: tmp_eigen(:),total_dos(:,:,:),eig_dos(:,:) 362 real(dp),allocatable :: dos_m(:,:,:),dos_paw1(:,:,:),dos_pawt1(:,:,:) 363 real(dp),allocatable :: wdt(:,:) 364 365 ! ********************************************************************* 366 367 !DEBUG 368 !write(std_out,*)' m_epjdos%dos_calcncwrite, enter ' 369 !ENDDEBUG 370 371 my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm); iam_master = (my_rank == master) 372 373 prtdosm = dos%prtdosm; paw_dos_flag = dos%paw_dos_flag 374 mbesslang = dos%mbesslang; ndosfraction = dos%ndosfraction 375 376 nkpt = dtset%nkpt; nsppol = dtset%nsppol 377 378 !m-decomposed DOS not compatible with PAW-decomposed DOS 379 if (prtdosm>=1.and.paw_dos_flag==1) then 380 msg = 'm-decomposed DOS (prtdosm>=1) not compatible with PAW-decomposed DOS (pawprtdos=1) !' 381 ABI_ERROR(msg) 382 end if 383 384 !Refuse nband different for different kpoints 385 !Note: This means we can pass ebands%eig(:,:,:) instead of eigen(mband*nkpt*nsppol) in packed form 386 do isppol=1,nsppol 387 do ikpt=1,nkpt 388 if ( dtset%nband(nkpt*(isppol-1) + ikpt) /= dtset%nband(1) ) then 389 write(std_out,*) 'tetrahedron: skip subroutine.' 390 write(std_out,*) 'nband must be the same for all kpoints' 391 write(std_out,*) 'nband=', dtset%nband 392 ABI_WARNING('tetrahedron: skip subroutine. See message above') 393 return 394 end if 395 end do 396 end do 397 398 call cwtime(cpu, wall, gflops, "start") 399 400 tetra = tetra_from_kptrlatt(crystal, dtset%kptopt, dtset%kptrlatt, dtset%nshiftk, & 401 dtset%shiftk, dtset%nkpt, dtset%kpt, comm, msg, ierr) 402 if (ierr /= 0) then 403 call tetra%free() 404 ABI_WARNING(msg) 405 return 406 end if 407 408 natsph=dtset%natsph; natsph_extra=dtset%natsph_extra 409 410 ! Master opens the DOS files. 411 if (iam_master) then 412 if (any(dtset%prtdos == [2, 5])) then 413 if (open_file(fildata, msg, newunit=unitdos, status='unknown', form='formatted', action="write") /= 0) then 414 ABI_ERROR(msg) 415 end if 416 417 else if (dtset%prtdos == 3) then 418 ! unt_atsph(0) is used for the total DOS. 419 ABI_MALLOC(unt_atsph,(0:natsph+natsph_extra)) 420 421 ! Open file for total DOS as well. 422 if (open_file(strcat(fildata, '_TOTAL'), msg, newunit=unt_atsph(0), & 423 status='unknown', form='formatted', action="write") /= 0) then 424 ABI_ERROR(msg) 425 end if 426 427 do iat=1,natsph 428 call int2char4(dtset%iatsph(iat),tag) 429 ABI_CHECK((tag(1:1)/='#'),'Bug: string length too short!') 430 if (open_file(strcat(fildata, '_AT', tag), msg, newunit=unt_atsph(iat), & 431 status='unknown', form='formatted', action="write") /= 0) then 432 ABI_ERROR(msg) 433 end if 434 end do 435 ! do extra spheres in vacuum too. Use _ATEXTRA[NUM] suffix 436 do iat=1,natsph_extra 437 call int2char4(iat,tag) 438 ABI_CHECK((tag(1:1)/='#'),'Bug: string length too short!') 439 if (open_file(strcat(fildata, '_ATEXTRA', tag), msg, newunit=unt_atsph(natsph+iat), & 440 status='unknown', form='formatted', action="write") /= 0) then 441 ABI_ERROR(msg) 442 end if 443 end do 444 end if 445 end if 446 447 ! Write the header of the DOS file, and determine the energy range and spacing 448 prtdos=dtset%prtdos 449 buffer=0.01_dp ! Size of the buffer around the min and max ranges 450 451 ! A Similar section is present is getnel. Should move all DOS stuff to m_ebands 452 ! Choose the lower and upper energies 453 enemax = maxval(ebands%eig) + buffer 454 enemin = minval(ebands%eig) - buffer 455 456 ! Extend the range to a nicer value 457 enemax=0.1_dp*ceiling(enemax*10._dp) 458 enemin=0.1_dp*floor(enemin*10._dp) 459 460 ! Choose the energy increment 461 if(abs(dtset%dosdeltae)<tol10)then 462 deltaene=0.001_dp 463 if(dtset%prtdos>=2)deltaene=0.0005_dp ! Higher resolution possible (and wanted) for tetrahedron 464 else 465 deltaene=dtset%dosdeltae 466 end if 467 nene=nint((enemax-enemin)/deltaene)+1 468 469 call xmpi_bcast(nene, master, comm, ierr) 470 if (iam_master) list_dp(1:3) = [deltaene, enemin, enemax] 471 call xmpi_bcast(list_dp, master, comm, ierr) 472 deltaene = list_dp(1); enemin = list_dp(2); enemax = list_dp(3) 473 474 if (iam_master) then 475 if (any(dtset%prtdos == [2, 5])) then 476 call dos_hdr_write(deltaene,ebands%eig,enemax,enemin,ebands%fermie,ebands%fermih,& 477 dtset%mband,dtset%nband,nene,nkpt,nsppol,dtset%occopt,prtdos,& 478 dtset%tphysel,dtset%tsmear,unitdos) 479 else if (dtset%prtdos == 3) then 480 do iat=0,natsph+natsph_extra 481 call dos_hdr_write(deltaene,ebands%eig,enemax,enemin,ebands%fermie,ebands%fermih,& 482 dtset%mband,dtset%nband,nene,nkpt,nsppol,dtset%occopt,prtdos,& 483 dtset%tphysel,dtset%tsmear,unt_atsph(iat)) 484 end do 485 end if 486 end if 487 488 ! Tetra weights 489 ABI_MALLOC(wdt, (nene, 2)) 490 491 ! Allocate arrays to store DOSes and fill with zeros. 492 ! 1--> DOS , 2--> IDOS 493 ABI_MALLOC(total_dos,(nene,ndosfraction,2)) 494 ABI_MALLOC(eig_dos, (nene, 2)) 495 496 if (paw_dos_flag==1) then 497 ABI_MALLOC(dos_paw1,(nene,ndosfraction,2)) 498 ABI_MALLOC(dos_pawt1,(nene,ndosfraction,2)) 499 end if 500 if (prtdosm>=1) then 501 ABI_MALLOC(dos_m, (nene,ndosfraction*mbesslang,2)) 502 end if 503 504 !Get maximum occupation value (2 or 1) 505 max_occ = one; if (dtset%nspinor == 1 .and. nsppol == 1) max_occ = two 506 507 !------------------------------------------------------------------- 508 !For each spin polarisation and band, interpolate band over kpoints 509 !calculate integration weights and DOS contib from 510 !------------------------------------------------------------------- 511 512 ! Workspace arrays. 513 ABI_MALLOC(tmp_eigen,(nkpt)) 514 515 cnt = 0 516 do isppol=1,nsppol 517 518 total_dos = zero; eig_dos = zero 519 if (prtdosm>=1) dos_m = zero 520 if (paw_dos_flag==1) then 521 dos_paw1 = zero; dos_pawt1 = zero 522 end if 523 524 do ikpt=1,nkpt 525 do iband=1,ebands%nband(ikpt+(isppol-1)*ebands%nkpt) 526 cnt = cnt + 1; if (mod(cnt, nprocs) /= my_rank) cycle ! Mpi parallelism. 527 528 ! Accumulate total DOS from eigenvalues (this is the **exact** total DOS) 529 tmp_eigen(:) = ebands%eig(iband, :, isppol) 530 call tetra%get_onewk(ikpt,bcorr0,nene,nkpt,tmp_eigen,enemin,enemax,max_occ,wdt) 531 wdt = wdt*ebands%wtk(ikpt) 532 eig_dos = eig_dos + wdt 533 534 ! Accumulate L-DOS. 535 do ii=1,2 536 do ifrac=1,ndosfraction 537 total_dos(:,ifrac,ii) = total_dos(:,ifrac,ii) + wdt(:,ii) * dos%fractions(ikpt,iband,isppol,ifrac) 538 end do 539 end do 540 541 if (paw_dos_flag==1) then 542 ! Accumulate L-DOS (on-site terms). 543 do ii=1,2 544 do ifrac=1,ndosfraction 545 dos_paw1(:,ifrac,ii) = dos_paw1(:,ifrac,ii) + wdt(:,ii) * dos%fractions_paw1(ikpt,iband,isppol,ifrac) 546 dos_pawt1(:,ifrac,ii) = dos_pawt1(:,ifrac,ii) + wdt(:,ii) * dos%fractions_pawt1(ikpt,iband,isppol,ifrac) 547 end do 548 end do 549 end if 550 551 if (prtdosm>=1) then 552 ! Accumulate LM-DOS. 553 do ii=1,2 554 do ifrac=1,ndosfraction*mbesslang 555 dos_m(:,ifrac,ii) = dos_m(:,ifrac,ii) + wdt(:,ii) * dos%fractions_m(ikpt, iband, isppol, ifrac) 556 end do 557 end do 558 end if 559 560 end do ! ikpt 561 end do ! iband 562 563 ! Collect results on master 564 call xmpi_sum_master(eig_dos, master, comm, ierr) 565 call xmpi_sum_master(total_dos, master, comm, ierr) 566 bigDOS=(maxval(total_dos(:,:,1))>999._dp) 567 568 if (paw_dos_flag == 1) then 569 call xmpi_sum_master(dos_paw1, master, comm, ierr) 570 call xmpi_sum_master(dos_pawt1, master, comm, ierr) 571 end if 572 if (prtdosm >= 1) call xmpi_sum_master(dos_m, master, comm, ierr) 573 574 ! Write the DOS value in the DOS file 575 ! Print the data for this energy. Note the upper limit (dos_max), to be consistent with the format. 576 ! The use of "E" format is not adequate, for portability of the self-testing procedure. 577 ! header lines depend on the type of DOS (projected etc...) which is output 578 579 if (.not. iam_master) goto 10 580 call write_extra_headers() 581 582 if (prtdos==2) then 583 ! E, DOS, IDOS 584 do iene=1,nene 585 write(unitdos, '(f11.5,1x,2(f10.4,1x))') & 586 enemin + (iene-1)*deltaene, min(total_dos(iene,:,1), dos_max), total_dos(iene,:,2) 587 end do 588 589 else if (prtdos==3) then 590 591 ! Write E, DOS, IDOS 592 do iene=1,nene 593 write(unt_atsph(0), '(f11.5,1x,2(f10.4,1x))') & 594 enemin + (iene-1)*deltaene, min(eig_dos(iene,1), dos_max), eig_dos(iene,2) 595 end do 596 597 ! E, DOS(L=1,LMAX), IDOS(L=1,LMAX) 598 ! Here we assume mpsang = 5 in the format. 599 if (paw_dos_flag/=1.or.dtset%pawprtdos==2) then 600 frmt = '(f11.5,1x,5(f9.4,1x),10x,5(f8.2,1x),10x,25(f8.2,1x))' 601 if (bigDOS) frmt = '(f11.5,1x,5(f10.4,1x),10x,5(f8.2,1x),10x,25(f8.2,1x))' 602 ! for extra atoms in vacuum need more precision 603 frmt_extra = '(f11.5,1x,5(f20.16,1x),10x,5(f20.16,1x),10x,25(f20.16,1x))' 604 605 do iat=1,natsph 606 i1 = (iat-1)*mbesslang+1; i2 = iat*mbesslang 607 if (prtdosm==0) then 608 do iene=1,nene 609 write(unt_atsph(iat), fmt=frmt) enemin + (iene-1)*deltaene, & 610 min(total_dos(iene, i1:i2, 1), dos_max), total_dos(iene, i1:i2,2) 611 end do 612 else 613 do iene=1,nene 614 write(unt_atsph(iat), fmt=frmt) enemin + (iene-1)*deltaene, & 615 min(total_dos(iene, i1:i2, 1), dos_max),& 616 total_dos(iene, i1:i2, 2),& 617 min(dos_m(iene,(iat-1)*mbesslang**2+1:iat*mbesslang**2,1), dos_max) 618 end do 619 end if 620 end do 621 622 ! Extra spheres. 623 do iat=natsph+1,natsph+natsph_extra 624 i1 = (iat-1)*mbesslang+1; i2 = iat*mbesslang 625 if (prtdosm==0) then 626 do iene=1,nene 627 write(unt_atsph(iat), fmt=frmt_extra) enemin + (iene-1)*deltaene, & 628 total_dos(iene, i1:i2, 1), & 629 total_dos(iene, i1:i2, 2) 630 end do 631 else 632 do iene=1,nene 633 write(unt_atsph(iat), fmt=frmt_extra) enemin + (iene-1)*deltaene, & 634 total_dos(iene, i1:i2, 1),& 635 total_dos(iene, i1:i2, 2),& 636 dos_m(iene,(iat-1)*mbesslang**2+1:iat*mbesslang**2, 1) 637 end do 638 end if 639 end do 640 641 else 642 frmt = '(f11.5,1x,5(f9.4,1x),3(6x,5f9.4))' 643 if (bigDOS) frmt = '(f11.5,1x,5(f10.4,1x),3(6x,5f10.4))' 644 ! for extra atom spheres in vacuum need more precision 645 frmt_extra = '(f11.5,1x,5(f20.16,1x),3(6x,5f20.16))' 646 647 do iat=1,natsph 648 i1 = iat*5-4; i2 = iat*5 649 do iene=1,nene 650 write(unt_atsph(iat), fmt=frmt) enemin + (iene-1)*deltaene, & 651 min(total_dos(iene,i1:i2,1), dos_max),& 652 min(total_dos(iene,i1:i2,1) - dos_paw1(iene,i1:i2,1) + dos_pawt1(iene,i1:i2,1), dos_max),& 653 min(dos_paw1(iene,i1:i2,1), dos_max),& 654 min(dos_pawt1(iene,i1:i2,1), dos_max) 655 end do 656 end do 657 658 ! Extra spheres. 659 do iat=natsph+1,natsph+natsph_extra 660 i1 = iat*5-4; i2 = iat*5 661 do iene=1,nene 662 write(unt_atsph(iat), fmt=frmt_extra) enemin + (iene-1)*deltaene, & 663 min(total_dos(iene,i1:i2,1), dos_max),& 664 min(total_dos(iene,i1:i2,1) - dos_paw1(iene,i1:i2,1) + dos_pawt1(iene,i1:i2,1), dos_max),& 665 min(dos_paw1(iene,i1:i2,1), dos_max),& 666 min(dos_pawt1(iene,i1:i2,1), dos_max) 667 end do 668 end do 669 end if 670 671 else if (prtdos==5)then 672 ! E, SPIN-DOS 673 frmt = '(f11.5,1x,7(f9.4,1x),10x,7(f8.2,1x))' 674 if (bigDOS) frmt = '(f11.5,1x,7(f10.4,1x),10x,7(f8.2,1x))' 675 do iene=1,nene 676 write(unitdos, fmt=frmt) enemin + (iene-1)*deltaene, min(total_dos(iene,1:7,1), dos_max), total_dos(iene,1:7,2) 677 end do 678 end if 679 680 10 continue 681 integral_DOS=sum(total_dos(nene,:,2)) 682 write(msg, '(a,es16.8)' ) ' tetrahedron : integrate to',integral_DOS 683 call wrtout(std_out,msg,'COLL') 684 end do ! isppol 685 686 ! Close files. 687 if (iam_master) then 688 if (any(prtdos == [2, 5])) then 689 close(unitdos) 690 else if (prtdos == 3) then 691 do iat=0,natsph+natsph_extra 692 close(unt_atsph(iat)) 693 end do 694 ABI_FREE(unt_atsph) 695 end if 696 end if 697 698 ABI_FREE(tmp_eigen) 699 ABI_FREE(total_dos) 700 ABI_FREE(wdt) 701 ABI_FREE(eig_dos) 702 703 if (prtdosm>=1) then 704 ABI_FREE(dos_m) 705 end if 706 707 if (paw_dos_flag==1) then 708 ABI_FREE(dos_paw1) 709 ABI_FREE(dos_pawt1) 710 end if 711 712 call tetra%free() 713 714 call cwtime(cpu,wall,gflops,"stop") 715 write(msg,'(2(a,f8.2),a)')" tetrahedron: cpu_time: ",cpu,"[s], walltime: ",wall," [s]" 716 call wrtout(std_out,msg,"PERS") 717 718 !DEBUG 719 !write(std_out,*)' m_epjdos%dos_calcncwrite, exit ' 720 !ENDDEBUG 721 722 contains 723 724 subroutine write_extra_headers() 725 726 if (nsppol==2) then 727 if(isppol==1) write(msg,'(a,16x,a)') '#','Spin-up DOS' 728 if(isppol==2) write(msg,'(2a,16x,a)') ch10,'#','Spin-dn DOS' 729 ! NB: dtset%prtdos == 5 should not happen for nsppol==2 730 731 if (any(dtset%prtdos == [2, 5])) then 732 write(unitdos, "(a)")trim(msg) 733 734 else if (dtset%prtdos == 3) then 735 do iat=0,natsph+natsph_extra 736 write(unt_atsph(iat), "(a)")trim(msg) 737 end do 738 end if 739 740 end if 741 742 if (prtdos==2) then 743 write(unitdos, '(a)' )'# energy(Ha) DOS integrated DOS' 744 745 else if (prtdos==3) then 746 747 write(unt_atsph(0), '(a)' )'# energy(Ha) DOS integrated DOS' 748 749 if (paw_dos_flag/=1.or.dtset%pawprtdos==2) then 750 do iat=1,natsph 751 write(unt_atsph(iat), '(3a,i5,a,i5,a,a,es16.6,3a)' ) & 752 '# Local DOS (columns 2-6) and integrated local DOS (columns 7-11),',ch10,& 753 '# for atom number iat=',iat,' iatom=',dtset%iatsph(iat),ch10,& 754 '# inside sphere of radius ratsph=',dtset%ratsph(dtset%typat(dtset%iatsph(iat))),' Bohr.',ch10,"#" 755 756 if (dtset%usepaw==1.and.dtset%pawprtdos==2) then 757 write(unt_atsph(iat), '(3a)' ) & 758 '# PAW: note that only all-electron on-site part has been used to compute DOS !',ch10,"#" 759 end if 760 if (bigDOS) then 761 write(msg, '(a,a)' ) & 762 '# energy(Ha) l=0 l=1 l=2 l=3 l=4',& 763 ' (integral=>) l=0 l=1 l=2 l=3 l=4' 764 else 765 write(msg, '(a,a)' ) & 766 '# energy(Ha) l=0 l=1 l=2 l=3 l=4',& 767 ' (integral=>) l=0 l=1 l=2 l=3 l=4' 768 end if 769 if (prtdosm>=1) then 770 write(msg, '(7a)' ) trim(msg),' ',& 771 ' lm=0 0',& 772 ' lm=1-1 lm=1 0 lm=1 1',& 773 ' lm=2-2 lm=2-1 lm=2 0 lm=2 1 lm=2 2',& 774 ' lm=3-3 lm=3-2 lm=3-1 lm=3 0 lm=3 1 lm=3 2 lm=3 3',& 775 ' lm=4-4 lm=4-3 lm=4-2 lm=4-1 lm=4 0 lm=4 1 lm=4 2 lm=4 3 lm=4 4' 776 end if 777 write(unt_atsph(iat), "(a)")trim(msg) 778 end do 779 else 780 do iat=1,natsph 781 write(unt_atsph(iat), '(9a,i5,a,i5,a,a,es16.6,3a)' ) & 782 '# Local DOS (columns 2-6),',ch10,& 783 '# plane-waves contrib. to DOS (columns 7-11),',ch10,& 784 '# AE on-site contrib. to DOS (columns 12-16),',ch10,& 785 '# -PS on-site contrib. to DOS (columns 17-21),',ch10,& 786 '# for atom number iat=',iat,' iatom=',dtset%iatsph(iat),ch10,& 787 '# inside sphere of radius ratsph=',dtset%ratsph(dtset%typat(dtset%iatsph(iat))),' Bohr.',ch10,"#" 788 if (bigDOS) then 789 write(msg, '(4a)' ) & 790 '#energy(Ha) l=0 l=1 l=2 l=3 l=4',& 791 ' (PW) l=0 l=1 l=2 l=3 l=4',& 792 ' (Phi) l=0 l=1 l=2 l=3 l=4',& 793 ' (tPhi) l=0 l=1 l=2 l=3 l=4' 794 else 795 write(msg, '(4a)' ) & 796 '#energy(Ha) l=0 l=1 l=2 l=3 l=4',& 797 ' (PW) l=0 l=1 l=2 l=3 l=4',& 798 ' (Phi) l=0 l=1 l=2 l=3 l=4',& 799 ' (tPhi) l=0 l=1 l=2 l=3 l=4' 800 end if 801 write(unt_atsph(iat), "(a)")trim(msg) 802 end do 803 end if 804 do iat=1,natsph_extra 805 write(unt_atsph(natsph+iat), '(3a,i5,2a,es16.6,3a)' ) & 806 '# Local DOS (columns 2-6) and integrated local DOS (columns 7-11),',ch10,& 807 '# for non-atomic sphere number iat=',iat,ch10,& 808 '# of radius ratsph=',dtset%ratsph_extra,' Bohr.',ch10,"#" 809 if (bigDOS) then 810 write(msg, '(a,a)' ) & 811 '# energy(Ha) l=0 l=1 l=2 l=3 l=4',& 812 ' (integral=>) l=0 l=1 l=2 l=3 l=4' 813 else 814 write(msg, '(a,a)' ) & 815 '# energy(Ha) l=0 l=1 l=2 l=3 l=4',& 816 ' (integral=>) l=0 l=1 l=2 l=3 l=4' 817 end if 818 if (prtdosm>=1) then 819 write(msg, '(7a)' ) trim(msg),' ',& 820 ' lm=0 0',& 821 ' lm=1-1 lm=1 0 lm=1 1',& 822 ' lm=2-2 lm=2-1 lm=2 0 lm=2 1 lm=2 2',& 823 ' lm=3-3 lm=3-2 lm=3-1 lm=3 0 lm=3 1 lm=3 2 lm=3 3',& 824 ' lm=4-4 lm=4-3 lm=4-2 lm=4-1 lm=4 0 lm=4 1 lm=4 2 lm=4 3 lm=4 4' 825 end if 826 write(unt_atsph(natsph+iat), "(a)")trim(msg) 827 end do 828 829 else if (prtdos==5) then 830 write(unitdos, '(a)' )& 831 '# energy(Ha) DOS up,up up,dn dn,up dn,dn sigma_x sigma_y sigma_z and integrated DOS components' 832 end if ! prtdos value 833 834 end subroutine write_extra_headers 835 836 end subroutine dos_calcnwrite
m_epjdos/epjdos_free [ Functions ]
[ Top ] [ m_epjdos ] [ Functions ]
NAME
epjdos_free
FUNCTION
deallocate memory
SOURCE
280 subroutine epjdos_free(self) 281 282 !Arguments ------------------------------------ 283 class(epjdos_t),intent(inout) :: self 284 285 ! ********************************************************************* 286 287 ! integer 288 ABI_SFREE(self%mlang_type) 289 290 ! real 291 ABI_SFREE(self%fractions) 292 ABI_SFREE(self%fractions_m) 293 ABI_SFREE(self%fractions_paw1) 294 ABI_SFREE(self%fractions_pawt1) 295 296 end subroutine epjdos_free
m_epjdos/epjdos_new [ Functions ]
[ Top ] [ m_epjdos ] [ Functions ]
NAME
epjdos_new
FUNCTION
Create new object from dataset input variables.
INPUTS
dtset <type(dataset_type)>=all input variables for this dataset psps <type(pseudopotential_type)>=variables related to pseudopotentials pawtab(ntypat*usepaw) <type(pawtab_type)>=paw tabulated starting data
SOURCE
171 type(epjdos_t) function epjdos_new(dtset, psps, pawtab) result(new) 172 173 !Arguments ------------------------------------ 174 type(dataset_type),intent(in) :: dtset 175 type(pseudopotential_type),intent(in) :: psps 176 type(pawtab_type),intent(in) :: pawtab(dtset%ntypat*psps%usepaw) 177 178 !Local variables------------------------------- 179 !scalars 180 integer :: ierr,itypat,iat 181 182 ! ********************************************************************* 183 184 !DEBUG 185 !write(std_out,*)' m_epjdos%epjdos_new, enter ' 186 !ENDDEBUG 187 188 new%nkpt = dtset%nkpt; new%mband = dtset%mband; new%nsppol = dtset%nsppol 189 190 new%prtdos = dtset%prtdos 191 new%partial_dos_flag = 0 192 if (new%prtdos==2) new%partial_dos_flag = 0 ! Standard DOS with tetra. 193 if (new%prtdos==3) new%partial_dos_flag = 1 ! L-DOS with tetra (prtdosm>0 if LM is wanted in Ylm/Slm basis). 194 if (new%prtdos==4) new%partial_dos_flag = 1 ! L-DOS with gaussian (prtdosm if LM is wanted in Ylm/Slm basis). 195 if (new%prtdos==5) new%partial_dos_flag = 2 ! Spin DOS 196 197 new%prtdosm=0 198 if (new%partial_dos_flag==1) new%prtdosm=dtset%prtdosm 199 ! paw_dos_flag= 1 if both PAW contributions are evaluated AND stored 200 new%paw_dos_flag=0 201 if (dtset%usepaw==1 .and. new%partial_dos_flag==1 .and. dtset%pawprtdos==1) new%paw_dos_flag=1 202 203 new%fatbands_flag=0 204 if (dtset%pawfatbnd>0 .and. new%prtdosm==0) new%fatbands_flag=1 205 if (new%prtdosm==1.and.dtset%pawfatbnd>0)then 206 ! because they compute quantities in real and complex harmonics respectively 207 ABI_ERROR('pawfatbnd>0 and prtdosm=1 are not compatible') 208 end if 209 210 ! mjv : initialization is needed as mbesslang is used for allocation below 211 ! NOTE: 10/5/2010 the whole of this could be looped over ndosfraction, 212 ! to store much less in memory. The DOS is accumulated in an array 213 ! and then printed to file at the end. 214 new%mbesslang = 1 215 if (new%partial_dos_flag==1 .or. new%fatbands_flag==1) then 216 217 ABI_MALLOC(new%mlang_type, (dtset%ntypat + dtset%natsph_extra)) 218 new%mlang_type = 0 219 220 ! TODO: Could use mbesslang = 4 or compute it from psps/pawtab 221 ! Increment by one (could underestimate if vloc = vlmax) 222 if (dtset%usepaw == 0) then 223 do iat=1,dtset%natsph 224 itypat = dtset%typat(dtset%iatsph(iat)) 225 new%mlang_type(itypat) = 1 + maxval(psps%indlmn(1, :, itypat)) 226 end do 227 else 228 do iat=1,dtset%natsph 229 itypat= dtset%typat(dtset%iatsph(iat)) 230 new%mlang_type(itypat) = 1 + (pawtab(itypat)%l_size - 1) / 2 231 end do 232 end if 233 234 ! Up to l=g if we have natsph_extra. 235 if (dtset%natsph_extra > 0) new%mlang_type(dtset%ntypat+1:) = 5 236 237 new%mlang_type = 5 ! This is to preserve the old implementation 238 new%mbesslang = maxval(new%mlang_type) 239 new%ndosfraction = (dtset%natsph + dtset%natsph_extra) * new%mbesslang 240 241 else if (new%partial_dos_flag == 2) then 242 new%ndosfraction = 7 243 244 else 245 new%ndosfraction = 1 246 new%mbesslang = 0 247 end if 248 249 ! Check allocations status as these arrays are not distributed and the wavefunctions are still in memory. 250 ABI_MALLOC_OR_DIE(new%fractions, (dtset%nkpt,dtset%mband,dtset%nsppol,new%ndosfraction), ierr) 251 new%fractions = zero 252 253 if (new%prtdosm>=1 .or. new%fatbands_flag==1) then 254 ABI_MALLOC_OR_DIE(new%fractions_m,(dtset%nkpt,dtset%mband,dtset%nsppol,new%ndosfraction*new%mbesslang), ierr) 255 new%fractions_m = zero 256 end if 257 258 if (dtset%usepaw==1 .and. new%partial_dos_flag==1) then 259 ABI_MALLOC_OR_DIE(new%fractions_paw1,(dtset%nkpt,dtset%mband,dtset%nsppol,new%ndosfraction), ierr) 260 ABI_MALLOC_OR_DIE(new%fractions_pawt1,(dtset%nkpt,dtset%mband,dtset%nsppol,new%ndosfraction), ierr) 261 new%fractions_paw1 = zero; new%fractions_pawt1 = zero 262 end if 263 264 !DEBUG 265 !write(std_out,*)' m_epjdos%epjdos_new, exit ' 266 !ENDDEBUG 267 268 end function epjdos_new
m_epjdos/epjdos_t [ Types ]
[ Top ] [ m_epjdos ] [ Types ]
NAME
epjdos_t
FUNCTION
Stores different contributions to the electronic DOS.
NOTES
Please contact gmatteo if you plan to change the internal implementation or add new DOSes. These results are saved in a netcdf file (see fatbands_ncwrite) so that one can read it with python and plot fatbands and PJDOSEs. The python version is able to handle the different cases (L, LM, Spin ...) but any change in the internal Abinit implementation is likely to break the python interface.
SOURCE
91 type,public :: epjdos_t 92 93 integer :: mbesslang 94 ! Max L+1 used in LM-DOS (Bessel function expansion) 95 96 integer :: ndosfraction 97 ! Defines the last dimension of the dos arrays. 98 ! Actual value depends on the other variables. 99 100 integer :: prtdos 101 ! 2 --> Standard DOS with tetra. 102 ! 3 --> L-DOS with tetra (prtdosm>0 if LM is wanted in Ylm/Slm basis). 103 ! 4 --> L-DOS with gaussian (prtdosm if LM is wanted in Ylm/Slm basis). 104 ! 5 --> Spin-DOS 105 106 integer :: prtdosm 107 ! Option for the m-contributions to the partial DOS 108 ! 1 if LM-projection is done onto complex Ylm 109 ! 2 if LM-projection is done onto real Slm 110 111 integer :: partial_dos_flag 112 113 integer :: paw_dos_flag 114 ! 1 if both PAW contributions are evaluated AND stored 115 116 !integer :: pawfatbnd 117 integer :: fatbands_flag 118 119 integer :: nkpt, mband, nsppol 120 ! Used to dimension arrays 121 122 integer,allocatable :: mlang_type(:) 123 ! mlang_type(ntypat + natsph_extra) 124 ! Max L+1 used in LM-DOS for each atom type 125 126 real(dp),allocatable :: fractions(:,:,:,:) 127 ! fractions(nkpt,mband,nsppol,ndosfraction)) 128 ! TODO: replace nsppol with nspden = 1, 2 (nsppol==2) or 4 (nspinor==2) 129 130 real(dp),allocatable :: fractions_m(:,:,:,:) 131 ! fractions_m(nkpt,mband,nsppol,ndosfraction*mbesslang) 132 133 real(dp),allocatable :: fractions_paw1(:,:,:,:) 134 ! fractions_paw1(nkpt,mband,nsppol,ndosfraction) 135 136 real(dp),allocatable :: fractions_pawt1(:,:,:,:) 137 ! fractions_pawt1(nkpt,mband,nsppol,ndosfraction)) 138 139 contains 140 141 procedure :: free => epjdos_free 142 ! Free dynamic memory 143 144 end type epjdos_t 145 146 public :: epjdos_new ! Create new object 147 148 149 public :: prtfatbands ! Print PJDOS contributions in xmgrace format. 150 public :: fatbands_ncwrite ! Write PJDOS contributions to netcdf file. 151 152 !---------------------------------------------------------------------- 153 154 contains !============================================================
m_epjdos/fatbands_ncwrite [ Functions ]
[ Top ] [ m_epjdos ] [ Functions ]
NAME
fatbands_ncwrite
FUNCTION
Write PJDOS contributions to netcdf file.
INPUTS
crystal<crystal_t>=Object defining the unit cell and its symmetries. ebands<ebands_t>=Band structure data. hdr<hdr_t>=Abinit header dtset<dtset_type>=Dataset type psps <type(pseudopotential_type)>=variables related to pseudopotentials pawtab(ntypat*usepaw) <type(pawtab_type)>=paw tabulated starting data ncid=NC file handle.
OUTPUT
Only writing
SOURCE
1715 subroutine fatbands_ncwrite(dos, crystal, ebands, hdr, dtset, psps, pawtab, ncid) 1716 1717 !Arguments ------------------------------------ 1718 !scalars 1719 integer,intent(in) :: ncid 1720 type(epjdos_t),intent(in) :: dos 1721 type(crystal_t),intent(in) :: crystal 1722 type(ebands_t),intent(in) :: ebands 1723 type(hdr_type),intent(in) :: hdr 1724 type(dataset_type),intent(in) :: dtset 1725 type(pseudopotential_type),intent(in) :: psps 1726 !arrays 1727 type(pawtab_type),intent(in) :: pawtab(dtset%ntypat*dtset%usepaw) 1728 1729 #ifdef HAVE_NETCDF 1730 !Local variables------------------------------- 1731 !scalars 1732 integer :: itype,ncerr,fform 1733 real(dp) :: cpu,wall,gflops 1734 character(len=500) :: msg 1735 !arrays 1736 integer :: lmax_type(crystal%ntypat) 1737 1738 !************************************************************************* 1739 1740 ABI_CHECK(dtset%natsph > 0, "natsph <=0") 1741 call cwtime(cpu, wall, gflops, "start") 1742 1743 fform = fform_from_ext("FATBANDS.nc") 1744 ABI_CHECK(fform /= 0, "Cannot find fform associated to FATBANDS.nc") 1745 1746 ! Write header, crystal structure and band energies. 1747 NCF_CHECK(hdr%ncwrite(ncid, fform, nc_define=.True.)) 1748 NCF_CHECK(crystal%ncwrite(ncid)) 1749 NCF_CHECK(ebands_ncwrite(ebands, ncid)) 1750 1751 ! Add fatband-specific quantities 1752 ncerr = nctk_def_dims(ncid, [ & 1753 nctkdim_t("natsph", dtset%natsph), & 1754 nctkdim_t("ndosfraction", dos%ndosfraction)], defmode=.True.) 1755 NCF_CHECK(ncerr) 1756 1757 if (dos%ndosfraction*dos%mbesslang > 0) then 1758 ncerr = nctk_def_dims(ncid, [ & 1759 nctkdim_t("mbesslang", dos%mbesslang), & 1760 nctkdim_t("dos_fractions_m_lastsize", dos%ndosfraction*dos%mbesslang)]) 1761 NCF_CHECK(ncerr) 1762 end if 1763 if (dtset%natsph_extra /= 0) then 1764 NCF_CHECK(nctk_def_dims(ncid, [nctkdim_t("natsph_extra", dtset%natsph_extra)])) 1765 end if 1766 1767 ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: "prtdos", "pawprtdos", "prtdosm"]) 1768 NCF_CHECK(ncerr) 1769 ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: "ratsph_extra"]) 1770 NCF_CHECK(ncerr) 1771 1772 ncerr = nctk_def_arrays(ncid, [& 1773 nctkarr_t("lmax_type", "int", "number_of_atom_species"), & 1774 nctkarr_t("iatsph", "int", "natsph"), & 1775 nctkarr_t("ratsph", "dp", "number_of_atom_species"), & 1776 nctkarr_t("dos_fractions", "dp", "number_of_kpoints, max_number_of_states, number_of_spins, ndosfraction") & 1777 ]) 1778 NCF_CHECK(ncerr) 1779 1780 if (allocated(dos%fractions_m)) then 1781 ncerr = nctk_def_arrays(ncid, & 1782 nctkarr_t("dos_fractions_m", "dp", & 1783 "number_of_kpoints, max_number_of_states, number_of_spins, dos_fractions_m_lastsize")) 1784 NCF_CHECK(ncerr) 1785 end if 1786 1787 if (allocated(dos%fractions_paw1)) then 1788 ncerr = nctk_def_arrays(ncid, [& 1789 nctkarr_t("dos_fractions_paw1", "dp", "number_of_kpoints, max_number_of_states, number_of_spins, ndosfraction"), & 1790 nctkarr_t("dos_fractions_pawt1", "dp", "number_of_kpoints, max_number_of_states, number_of_spins, ndosfraction") & 1791 ]) 1792 NCF_CHECK(ncerr) 1793 end if 1794 1795 if (dtset%natsph_extra /= 0) then 1796 ncerr = nctk_def_arrays(ncid, [& 1797 nctkarr_t("xredsph_extra", "dp", "number_of_reduced_dimensions, natsph_extra") & 1798 ]) 1799 NCF_CHECK(ncerr) 1800 end if 1801 1802 ! Write variables 1803 NCF_CHECK(nctk_set_datamode(ncid)) 1804 1805 ! scalars 1806 NCF_CHECK(nf90_put_var(ncid, vid("pawprtdos"), dtset%pawprtdos)) 1807 NCF_CHECK(nf90_put_var(ncid, vid("prtdos"), dos%prtdos)) 1808 NCF_CHECK(nf90_put_var(ncid, vid("prtdosm"), dos%prtdosm)) 1809 1810 ! arrays 1811 if (dtset%usepaw == 1) then 1812 lmax_type = (pawtab(:)%l_size - 1) / 2 1813 else 1814 do itype=1,crystal%ntypat 1815 lmax_type(itype) = maxval(psps%indlmn(1, :, itype)) 1816 end do 1817 end if 1818 NCF_CHECK(nf90_put_var(ncid, vid("lmax_type"), lmax_type)) 1819 NCF_CHECK(nf90_put_var(ncid, vid("dos_fractions"), dos%fractions)) 1820 1821 if (dos%prtdos == 3) then 1822 NCF_CHECK(nf90_put_var(ncid, vid("iatsph"), dtset%iatsph(1:dtset%natsph))) 1823 NCF_CHECK(nf90_put_var(ncid, vid("ratsph"), dtset%ratsph(1:dtset%ntypat))) 1824 NCF_CHECK(nf90_put_var(ncid, vid("ratsph_extra"), dtset%ratsph_extra)) 1825 if (dtset%natsph_extra /= 0) then 1826 NCF_CHECK(nf90_put_var(ncid, vid("xredsph_extra"), dtset%xredsph_extra(:, 1:dtset%natsph_extra))) 1827 end if 1828 end if 1829 1830 if (allocated(dos%fractions_m)) then 1831 NCF_CHECK(nf90_put_var(ncid, vid("dos_fractions_m"), dos%fractions_m)) 1832 end if 1833 if (allocated(dos%fractions_paw1)) then 1834 NCF_CHECK(nf90_put_var(ncid, vid("dos_fractions_paw1"), dos%fractions_paw1)) 1835 NCF_CHECK(nf90_put_var(ncid, vid("dos_fractions_pawt1"), dos%fractions_pawt1)) 1836 end if 1837 1838 call cwtime(cpu,wall,gflops,"stop") 1839 write(msg,'(2(a,f8.2),a)')" fatbands_ncwrite: cpu_time: ",cpu,"[s], walltime: ",wall," [s]" 1840 call wrtout(std_out,msg,"PERS") 1841 #endif 1842 1843 contains 1844 integer function vid(vname) 1845 character(len=*),intent(in) :: vname 1846 vid = nctk_idname(ncid, vname) 1847 end function vid 1848 1849 end subroutine fatbands_ncwrite
m_epjdos/partial_dos_fractions [ Functions ]
[ Top ] [ m_epjdos ] [ Functions ]
NAME
partial_dos_fractions
FUNCTION
calculate partial DOS fractions to feed to the tetrahedron method 1: project states on angular momenta 2: should be able to choose certain atoms or atom types, slabs of space...
INPUTS
crystal<crystal_t>= data type gathering info on symmetries and unit cell dtset<type(dataset_type)>=all input variables for this dataset npwarr(nkpt)=number of planewaves in basis at this k point kg(3,mpw*mkmem)=reduced planewave coordinates. cg(2,mcg)=planewave coefficients of wavefunctions mcg=size of wave-functions array (cg) =mpw*my_nspinor*mband*mkmem*nsppol collect=1 if fractions should be MPI collected at the end, 0 otherwise. mpi_enreg=information about MPI parallelization
SIDE EFFECTS
dos%fractions(ikpt,iband,isppol,ndosfraction) = percentage of s, p, d.. character on each atom for the wavefunction # ikpt,iband, isppol == if prtdosm /= 0 dos%fractions_m(ikpt,iband,isppol,ndosfraction*mbesslang) = percentage of s, p, d.. character on each atom for the wavefunction # ikpt,iband, isppol (m-resolved)
NOTES
psi(r) = (4pi/sqrt(ucvol)) \sum_{LMG} i**l u(G) e^{i(k+G).Ra} x Y_{LM}^*(k+G) Y_{LM}(r-Ra) j_L(|k+G||r-Ra|) int_(ratsph) |psi(r)|**2 = \sum_LM rho(LM) where rho_{LM} = 4pi \int_o^{rc} dr r**2 ||\sum_G u(G) Y_LM^*(k+G) e^{i(k+G).Ra} j_L(|k+G| r)||**2 where S is a RSH. The final expression is: When k = G0/2, we have u_{G0/2}(G) = u_{G0/2}(-G-G0)^* and P can be rewritten as P = (4pi i^L}/sqrt(ucvol) \sum^'_G w(G) S_{LM}(k+G) \int_0^ratsph dr r^2 j_L(|k+G|r) x 2 Re[u_k(G) e^{i(k+G).R_atom}] if L = 2n 2 Im[u_k(G) e^{i(k+G).R_atom}] if L = 2n + 1 where the sum over G is done on the reduced G-sphere and w(G) = 1/2 if G=G0 else 1.
SOURCE
1900 subroutine partial_dos_fractions(dos,crystal,dtset,eigen,occ,npwarr,kg,cg,mcg,collect,mpi_enreg) 1901 1902 !Arguments ------------------------------------ 1903 !scalars 1904 integer,intent(in) :: mcg,collect 1905 type(epjdos_t),intent(inout) :: dos 1906 type(MPI_type),intent(inout) :: mpi_enreg 1907 type(dataset_type),intent(in) :: dtset 1908 type(crystal_t),intent(in) :: crystal 1909 !arrays 1910 integer,intent(in) :: kg(3,dtset%mpw*dtset%mkmem),npwarr(dtset%nkpt) 1911 real(dp),intent(in) :: cg(2,mcg) 1912 real(dp),intent(in) :: eigen(dtset%mband*dtset%nkpt*dtset%nsppol) 1913 real(dp),intent(in) :: occ(dtset%mband*dtset%nkpt*dtset%nsppol) 1914 1915 !Local variables------------------------------- 1916 !scalars 1917 integer,parameter :: prtsphere0=0 ! do not output all the band by band details for projections. 1918 integer :: shift_b,shift_sk,iat,iatom,iband,ierr,ikpt,ilang,ioffkg,is1, is2, isoff 1919 integer :: ipw,isppol,ixint,mbess,mcg_disk,me_kpt,shift_cg 1920 integer :: mgfft,my_nspinor,n1,n2,n3,natsph_tot,npw_k,nradintmax 1921 integer :: rc_ylm,itypat,nband_k 1922 integer :: abs_shift_b 1923 integer :: unit_procar, ipauli 1924 real(dp),parameter :: bessint_delta = 0.1_dp 1925 real(dp) :: arg,bessarg,bessargmax,kpgmax,rmax 1926 real(dp) :: cpu,wall,gflops 1927 character(len=500) :: msg 1928 character(len=4) :: ikproc_str 1929 character(len=fnlen) :: filename 1930 type(jlspline_t) :: jlspl 1931 type(MPI_type) :: mpi_enreg_seq 1932 !arrays 1933 integer :: iindex(dtset%mpw),nband_tmp(1),npwarr_tmp(1) 1934 integer,allocatable :: iatsph(:),nradint(:),atindx(:),typat_extra(:),kg_k(:,:) 1935 real(dp) :: kpoint(3),spin(3),ylmgr_dum(1) 1936 real(dp) :: xfit(dtset%mpw),yfit(dtset%mpw) 1937 real(dp),allocatable :: ylm_k(:,:) 1938 real(dp),allocatable :: bess_fit(:,:,:) 1939 real(dp),allocatable :: cg_1band(:,:),cg_1kpt(:,:),kpgnorm(:),ph1d(:,:) 1940 real(dp),allocatable :: ph3d(:,:,:),ratsph(:),rint(:),sum_1ll_1atom(:,:,:) 1941 real(dp),allocatable :: sum_1lm_1atom(:,:,:) 1942 real(dp),allocatable :: cplx_1lm_1atom(:,:,:,:) 1943 real(dp),allocatable :: xred_sph(:,:),znucl_sph(:),phkxred(:,:) 1944 complex(dpc) :: cgcmat(2,2) 1945 1946 !************************************************************************* 1947 1948 !DEBUG 1949 !write(std_out, '(a)') ' m_epjdos%partial_dos_fractions : enter ' 1950 !ENDDEBUG 1951 1952 if(dtset%natsph==dtset%natom)then 1953 write(msg, '(a)') ' Compute the partial DOS fractions. This can be time-consuming. Think using natsph and iatsph.' 1954 else 1955 write(msg, '(a)') ' Compute the partial DOS fractions.' 1956 endif 1957 call wrtout(std_out,msg,'COLL') 1958 1959 ! for the moment, only support projection on angular momenta 1960 if (dos%partial_dos_flag /= 1 .and. dos%partial_dos_flag /= 2) then 1961 write(std_out,*) 'Error: partial_dos_fractions only supports angular ' 1962 write(std_out,*) ' momentum projection and spinor components for the moment. return to outscfcv' 1963 write(std_out,*) ' partial_dos = ', dos%partial_dos_flag 1964 return 1965 end if 1966 1967 ! impose all kpoints have same number of bands 1968 do isppol=1,dtset%nsppol 1969 do ikpt=1,dtset%nkpt 1970 if (dtset%nband((isppol-1)*dtset%nkpt + ikpt) /= dtset%mband) then 1971 write(std_out,*) 'Error: partial_dos_fractions wants same number of bands at each kpoint' 1972 write(std_out,*) ' isppol, ikpt = ', isppol,ikpt, dtset%nband((isppol-1)*dtset%nkpt + ikpt), dtset%mband 1973 write(std_out,*) ' all nband = ', dtset%nband 1974 return 1975 end if 1976 end do 1977 end do 1978 1979 ! Real or complex spherical harmonics? 1980 rc_ylm = 2; if (dos%prtdosm == 2) rc_ylm = 1 1981 1982 me_kpt = mpi_enreg%me_kpt 1983 my_nspinor = max(1,dtset%nspinor/mpi_enreg%nproc_spinor) 1984 1985 n1 = dtset%ngfft(1); n2 = dtset%ngfft(2); n3 = dtset%ngfft(3) 1986 mgfft = maxval(dtset%ngfft(1:3)) 1987 1988 call cwtime(cpu, wall, gflops, "start") 1989 1990 if (dtset%prtprocar /= 0) then 1991 ! open file for each proc, and print header for master node 1992 call int2char4(me_kpt, ikproc_str) 1993 filename = 'PROCAR_'//ikproc_str 1994 if (open_file(filename, msg, newunit=unit_procar, form="formatted", action="write") /= 0) then 1995 ABI_ERROR(msg) 1996 end if 1997 if(mpi_enreg%me==0) then 1998 write (unit_procar,'(a)') 'PROCAR lm decomposed - need to merge files yourself in parallel case!!! Or use pyprocar package' 1999 if (dtset%prtprocar == 2) then 2000 write (unit_procar,'(a)') ' Requested complex output of PROCAR file (prtprocar 2)' 2001 end if 2002 write (unit_procar,'(a,I10,a,I10,a,I10,a)') '# of k-points: ', dtset%nkpt, & 2003 ' # of bands:', dtset%mband, ' # of ions:', dtset%natom, ch10 2004 end if 2005 end if 2006 2007 !############################################################## 2008 !FIRST CASE: project on angular momenta to get dos parts 2009 !############################################################## 2010 2011 if (dos%partial_dos_flag == 1) then 2012 natsph_tot = dtset%natsph + dtset%natsph_extra 2013 2014 ABI_MALLOC(iatsph, (natsph_tot)) 2015 ABI_MALLOC(typat_extra, (natsph_tot)) 2016 ABI_MALLOC(ratsph, (natsph_tot)) 2017 ABI_MALLOC(znucl_sph, (natsph_tot)) 2018 ABI_MALLOC(nradint, (natsph_tot)) 2019 ABI_MALLOC(atindx, (natsph_tot)) 2020 ABI_MALLOC(phkxred, (2,natsph_tot)) 2021 2022 ! initialize atindx 2023 do iatom=1,natsph_tot 2024 atindx(iatom) = iatom 2025 end do 2026 2027 iatsph(1:dtset%natsph) = dtset%iatsph(1:dtset%natsph) 2028 do iatom=1,dtset%natsph 2029 itypat = dtset%typat(iatsph(iatom)) 2030 typat_extra(iatom) = itypat 2031 ratsph(iatom) = dtset%ratsph(itypat) 2032 znucl_sph(iatom) = dtset%znucl(itypat) 2033 end do 2034 2035 ! fictitious atoms are declared with 2036 ! %natsph_extra, %ratsph_extra and %xredsph_extra(3, dtset%natsph_extra) 2037 ! they have atom index (natom + ii) and itype = ntypat + 1 2038 do iatom=1,dtset%natsph_extra 2039 typat_extra(iatom+dtset%natsph) = dtset%ntypat + 1 2040 ratsph(iatom+dtset%natsph) = dtset%ratsph_extra 2041 znucl_sph(iatom+dtset%natsph) = zero 2042 iatsph(iatom+dtset%natsph) = dtset%natom + iatom 2043 end do 2044 2045 ! init bessel function integral for recip_ylm max ang mom + 1 2046 ABI_MALLOC(sum_1ll_1atom,(dtset%nspinor**2,dos%mbesslang,natsph_tot)) 2047 ABI_MALLOC(sum_1lm_1atom,(dtset%nspinor**2,dos%mbesslang**2,natsph_tot)) 2048 ABI_MALLOC(cplx_1lm_1atom,(2,dtset%nspinor,dos%mbesslang**2,natsph_tot)) 2049 2050 ! Note ecuteff instead of ecut. 2051 kpgmax = sqrt(dtset%ecut * dtset%dilatmx**2) 2052 rmax = zero; bessargmax = zero; nradintmax = 0 2053 do iatom=1,natsph_tot 2054 rmax = max(rmax, ratsph(iatom)) 2055 bessarg = ratsph(iatom)*two_pi*kpgmax 2056 bessargmax = max(bessargmax, bessarg) 2057 nradint(iatom) = int (bessarg / bessint_delta) + 1 2058 nradintmax = max(nradintmax,nradint(iatom)) 2059 end do 2060 !write(std_out,*)' partial_dos_fractions: rmax=', rmax,' nradintmax: ", nradintmax 2061 ! use same number of grid points to calculate Bessel function and to do the integration later on r 2062 ! and make sure bessargmax is a multiple of bessint_delta 2063 mbess = nradintmax 2064 bessargmax = bessint_delta*mbess 2065 2066 ABI_MALLOC(rint,(nradintmax)) 2067 ABI_MALLOC(bess_fit,(dtset%mpw,nradintmax,dos%mbesslang)) 2068 2069 ! initialize general Bessel function array on uniform grid xx, from 0 to (2 \pi |k+G|_{max} |r_{max}|) 2070 jlspl = jlspline_new(mbess, bessint_delta, dos%mbesslang) 2071 2072 ABI_MALLOC(xred_sph, (3, natsph_tot)) 2073 do iatom=1,dtset%natsph 2074 xred_sph(:,iatom) = crystal%xred(:,iatsph(iatom)) 2075 end do 2076 do iatom=1,dtset%natsph_extra 2077 xred_sph(:,dtset%natsph+iatom) = dtset%xredsph_extra(:, iatom) 2078 end do 2079 2080 ABI_MALLOC(ph1d,(2,(2*n1+1 + 2*n2+1 + 2*n3+1)*natsph_tot)) 2081 call getph(atindx,natsph_tot,n1,n2,n3,ph1d,xred_sph) 2082 2083 ! Fake MPI data to be used for sequential call to initylmg. 2084 call initmpi_seq(mpi_enreg_seq) 2085 mpi_enreg_seq%my_natom = dtset%natom 2086 2087 shift_sk = 0 2088 abs_shift_b = 0 ! offset to allow for automatic update with +1 below 2089 do isppol=1,dtset%nsppol 2090 ioffkg = 0 2091 2092 do ikpt=1,dtset%nkpt 2093 nband_k = dtset%nband((isppol-1)*dtset%nkpt + ikpt) 2094 if (proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,me_kpt)) then 2095 abs_shift_b = abs_shift_b + nband_k ! jump the whole kpt in the eig and occ arrays 2096 cycle 2097 end if 2098 npw_k = npwarr(ikpt) 2099 kpoint(:) = dtset%kpt(:,ikpt) 2100 2101 if (dtset%prtprocar /= 0) then 2102 write (unit_procar,'(a,I7,a,3F12.6,a,F12.6,a)') & 2103 ' k-point ', ikpt, ' : ', kpoint(:), ' weight = ', dtset%wtk(ikpt), ch10 2104 end if 2105 2106 ! make phkred for all atoms 2107 do iat=1,natsph_tot 2108 arg=two_pi*( kpoint(1)*xred_sph(1,iat) + kpoint(2)*xred_sph(2,iat) + kpoint(3)*xred_sph(3,iat) ) 2109 phkxred(1,iat)=cos(arg) 2110 phkxred(2,iat)=sin(arg) 2111 end do 2112 2113 ABI_MALLOC(kg_k, (3, npw_k)) 2114 kg_k = kg(:,ioffkg+1:ioffkg+npw_k) 2115 2116 ! kpgnorm contains norms only for kpoints used by this processor 2117 ABI_MALLOC(kpgnorm, (npw_k)) 2118 call getkpgnorm(crystal%gprimd, kpoint, kg_k, kpgnorm, npw_k) 2119 2120 ! Now get Ylm(k, G) factors: returns "real Ylms", which are real (+m) and 2121 ! imaginary (-m) parts of actual complex Ylm. Yl-m = Ylm* 2122 ! Call initylmg for a single k-point (mind mpi_enreg_seq). 2123 ABI_MALLOC(ylm_k, (npw_k, dos%mbesslang**2)) 2124 npwarr_tmp(1) = npw_k; nband_tmp(1) = nband_k 2125 call initylmg(crystal%gprimd,kg_k,kpoint,1,mpi_enreg_seq,dos%mbesslang,& 2126 npw_k,nband_tmp,1,npwarr_tmp,1,0,crystal%rprimd,ylm_k,ylmgr_dum) 2127 2128 ! get phases exp (2 pi i (k+G).x_tau) in ph3d 2129 ABI_MALLOC(ph3d,(2,npw_k,natsph_tot)) 2130 call ph1d3d(1,natsph_tot,kg_k,natsph_tot,natsph_tot,npw_k,n1,n2,n3,phkxred,ph1d,ph3d) 2131 2132 ! get Bessel function factors on array of |k+G|*r distances 2133 ! since we need many r distances and have a large number of different 2134 ! |k+G|, get j_l on uniform grid (above, in array gen_besj), 2135 ! and spline it for each kpt Gvector set. 2136 ! Note that we use the same step based on rmax, this can lead to (hopefully small) 2137 ! inaccuracies when we integrate from 0 up to rmax(iatom) 2138 do ixint=1,nradintmax 2139 rint(ixint) = (ixint-1)*rmax / (nradintmax-1) 2140 do ipw=1,npw_k 2141 xfit(ipw) = two_pi * kpgnorm(ipw) * rint(ixint) 2142 iindex(ipw) = ipw 2143 end do 2144 2145 call sort_dp(npw_k,xfit,iindex,tol14) 2146 do ilang=1,dos%mbesslang 2147 call splint(mbess, jlspl%xx, jlspl%bess_spl(:,ilang), jlspl%bess_spl_der(:,ilang), npw_k, xfit, yfit) 2148 ! re-order results for different G vectors 2149 do ipw=1,npw_k 2150 bess_fit(iindex(ipw),ixint,ilang) = yfit(ipw) 2151 end do 2152 end do 2153 end do ! ixint 2154 2155 shift_b = 0 2156 do iband=1,nband_k 2157 abs_shift_b = abs_shift_b + 1 2158 if (proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,iband,iband,isppol,me_kpt)) cycle 2159 !write(std_out,*)"in band:",iband 2160 ! TODO: eventually import eig and occ down to here - a pain, but printing outside would imply saving a huge array in memory 2161 if (dtset%prtprocar /= 0) then 2162 write (unit_procar,'(a,I7,a,F12.6,a,F12.6,a)') 'band ', iband, ' # energy ', & 2163 eigen(abs_shift_b), ' # occ. ', occ(abs_shift_b), ch10 2164 end if 2165 2166 ! Select wavefunction in cg array 2167 shift_cg = shift_sk + shift_b 2168 2169 call recip_ylm(bess_fit, cg(:,shift_cg+1:shift_cg+my_nspinor*npw_k), dtset%istwfk(ikpt),& 2170 & mpi_enreg, nradint, nradintmax, dos%mbesslang , dtset%mpw, natsph_tot, typat_extra, dos%mlang_type,& 2171 & npw_k, dtset%nspinor, ph3d, prtsphere0, rint, ratsph, rc_ylm, sum_1ll_1atom, sum_1lm_1atom, cplx_1lm_1atom,& 2172 & crystal%ucvol, ylm_k, znucl_sph) 2173 ! on exit the sum_1atom_* have both spinors counted 2174 2175 ! Accumulate 2176 do iatom=1,natsph_tot 2177 do ilang=1,dos%mbesslang 2178 dos%fractions(ikpt,iband,isppol,dos%mbesslang*(iatom-1) + ilang) & 2179 & = dos%fractions(ikpt,iband,isppol,dos%mbesslang*(iatom-1) + ilang) & 2180 & + sum_1ll_1atom(1,ilang,iatom) 2181 end do 2182 end do 2183 2184 if (dos%prtdosm /= 0) then 2185 do iatom=1,natsph_tot 2186 do ilang=1,dos%mbesslang**2 2187 dos%fractions_m(ikpt,iband,isppol,dos%mbesslang**2*(iatom-1) + ilang) & 2188 & = dos%fractions_m(ikpt,iband,isppol,dos%mbesslang**2*(iatom-1) + ilang) & 2189 & + sum_1lm_1atom(1,ilang,iatom) 2190 end do 2191 end do 2192 end if 2193 2194 ! Increment band, spinor shift 2195 !shift_b = shift_b + npw_k 2196 shift_b = shift_b + my_nspinor*npw_k 2197 2198 ! now we have both spinor components. The first option is for real values projections, eventually decomposed by Pauli spinor components 2199 if (dtset%prtprocar /= 0) then 2200 write (unit_procar,'(a)') 'ion s py pz px dxy dyz dz2 dxz dx2 tot' 2201 do ipauli= 1,dtset%nspinor**2 2202 ! Contract with Pauli matrices to get projections for this k and band, all atoms and ilang 2203 do iatom = 1, natsph_tot 2204 write (unit_procar, '(1x,I5)', advance='no') iatom 2205 do ilang=1,min(dos%mbesslang**2,9) 2206 write (unit_procar, '(F7.3)',advance='no') sum_1lm_1atom(ipauli,ilang,iatom) 2207 end do 2208 write (unit_procar, '(F7.3)',advance='yes') sum(sum_1lm_1atom(ipauli,:,iatom)) 2209 end do 2210 ! final line with sum over atoms 2211 write (unit_procar, '(a)', advance='no') 'tot ' 2212 do ilang=1,min(dos%mbesslang**2,9) 2213 write (unit_procar, '(F7.3)',advance='no') sum(sum_1lm_1atom(ipauli,ilang,:)) 2214 end do 2215 write (unit_procar, '(F7.3)',advance='yes') sum(sum_1lm_1atom(ipauli,:,:)) 2216 end do 2217 2218 ! second option is to also print the complex projection on the atomic like orbital: <psi_nk | Y_lm> in a sphere 2219 ! Two blocks are printed, first real then imaginary part 2220 if (dtset%prtprocar == 2) then 2221 write (unit_procar,'(2a)') 'ion s py pz px',& 2222 & ' dxy dyz dz2 dxz dx2 tot' 2223 do is1= 1,dtset%nspinor 2224 ! Contracted with Pauli matrices to get projections for this k and band, all atoms and ilang 2225 do iatom = 1, natsph_tot 2226 write (unit_procar, '(1x,I5)', advance='no') iatom 2227 do ilang=1,min(dos%mbesslang**2,9) 2228 write (unit_procar, '(2(F7.3,1x))',advance='no') cplx_1lm_1atom(:,is1,ilang,iatom) 2229 end do 2230 write (unit_procar, '(2(F7.3,1x))',advance='yes') sum(cplx_1lm_1atom(1,is1,:,iatom)), & 2231 & sum(cplx_1lm_1atom(2,is1,:,iatom)) 2232 end do 2233 ! final line with sum over atoms 2234 write (unit_procar, '(a)', advance='no') 'charge' 2235 do ilang=1,min(dos%mbesslang**2,9) 2236 write (unit_procar, '(F7.3,9x)',advance='no') sum(cplx_1lm_1atom(:,is1,ilang,:)**2) 2237 end do 2238 write (unit_procar, '(F7.3,9x)',advance='yes') sum(cplx_1lm_1atom(:,is1,:,:)**2) 2239 end do 2240 write (unit_procar,*) 2241 end if 2242 end if 2243 2244 end do ! band 2245 2246 ! Increment kpt and (spin, kpt) shifts 2247 ioffkg = ioffkg + npw_k 2248 shift_sk = shift_sk + nband_k*my_nspinor*npw_k 2249 2250 ABI_FREE(kg_k) 2251 ABI_FREE(kpgnorm) 2252 ABI_FREE(ylm_k) 2253 ABI_FREE(ph3d) 2254 end do ! ikpt 2255 end do ! isppol 2256 2257 ! collect = 1 ==> gather all contributions from different processors 2258 if (collect == 1) then 2259 call xmpi_sum(dos%fractions,mpi_enreg%comm_kpt,ierr) 2260 if (dos%prtdosm /= 0) call xmpi_sum(dos%fractions_m,mpi_enreg%comm_kpt,ierr) 2261 2262 ! this is now done inside recip_ylm 2263 ! if (mpi_enreg%paral_spinor == 1)then 2264 ! call xmpi_sum(dos%fractions,mpi_enreg%comm_spinor,ierr) 2265 ! if (dos%prtdosm /= 0) call xmpi_sum(dos%fractions_m,mpi_enreg%comm_spinor,ierr) 2266 ! end if 2267 end if 2268 2269 ABI_FREE(atindx) 2270 ABI_FREE(bess_fit) 2271 ABI_FREE(iatsph) 2272 ABI_FREE(typat_extra) 2273 ABI_FREE(nradint) 2274 ABI_FREE(ph1d) 2275 ABI_FREE(phkxred) 2276 ABI_FREE(ratsph) 2277 ABI_FREE(rint) 2278 ABI_FREE(sum_1ll_1atom) 2279 ABI_FREE(sum_1lm_1atom) 2280 ABI_FREE(cplx_1lm_1atom) 2281 ABI_FREE(xred_sph) 2282 ABI_FREE(znucl_sph) 2283 2284 call jlspline_free(jlspl) 2285 call destroy_mpi_enreg(mpi_enreg_seq) 2286 2287 !############################################################## 2288 !2ND CASE: project on spinors 2289 !############################################################## 2290 2291 else if (dos%partial_dos_flag == 2) then 2292 2293 if (dtset%nsppol /= 1 .or. dtset%nspinor /= 2) then 2294 ABI_WARNING("spinor projection is meaningless if nsppol==2 or nspinor/=2. Not calculating projections.") 2295 return 2296 end if 2297 if (my_nspinor /= 2) then 2298 ABI_WARNING("spinor projection with spinor parallelization is not coded. Not calculating projections.") 2299 return 2300 end if 2301 ABI_CHECK(mpi_enreg%paral_spinor == 0, "prtdos 5 does not support spinor parallelism") 2302 2303 ! FIXME: We should not allocate such a large chunk of memory! 2304 mcg_disk = dtset%mpw*my_nspinor*dtset%mband 2305 ABI_MALLOC(cg_1kpt,(2,mcg_disk)) 2306 shift_sk = 0 2307 isppol = 1 2308 2309 do ikpt=1,dtset%nkpt 2310 nband_k = dtset%nband((isppol-1)*dtset%nkpt + ikpt) 2311 if (proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,me_kpt)) cycle 2312 npw_k = npwarr(ikpt) 2313 2314 cg_1kpt(:,:) = cg(:,shift_sk+1:shift_sk+mcg_disk) 2315 ABI_MALLOC(cg_1band,(2,2*npw_k)) 2316 shift_b=0 2317 do iband=1,nband_k 2318 if (proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,iband,iband,isppol,me_kpt)) cycle 2319 2320 ! Select wavefunction in cg array 2321 !shift_cg = shift_sk + shift_b 2322 cg_1band(:,:) = cg_1kpt(:,shift_b+1:shift_b+2*npw_k) 2323 call cg_getspin(cg_1band, npw_k, spin, cgcmat=cgcmat) 2324 2325 ! MG: TODO: imag part of off-diagonal terms is missing. 2326 ! I will add them later on. 2327 do is1=1,2 2328 do is2=1,2 2329 isoff = is2 + (is1-1)*2 2330 dos%fractions(ikpt,iband,isppol,isoff) = dos%fractions(ikpt,iband,isppol,isoff) & 2331 & + real(cgcmat(is1,is2)) 2332 end do 2333 end do 2334 2335 dos%fractions(ikpt,iband,isppol,5) = dos%fractions(ikpt,iband,isppol,5) + spin(1) 2336 dos%fractions(ikpt,iband,isppol,6) = dos%fractions(ikpt,iband,isppol,6) + spin(2) 2337 dos%fractions(ikpt,iband,isppol,7) = dos%fractions(ikpt,iband,isppol,7) + spin(3) 2338 2339 shift_b = shift_b + 2*npw_k 2340 end do 2341 ABI_FREE(cg_1band) 2342 shift_sk = shift_sk + nband_k*2*npw_k 2343 end do 2344 ABI_FREE(cg_1kpt) 2345 2346 ! Gather all contributions from different processors 2347 if (collect == 1) then 2348 call xmpi_sum(dos%fractions,mpi_enreg%comm_kpt,ierr) 2349 call xmpi_sum(dos%fractions,mpi_enreg%comm_bandfft,ierr) 2350 !below for future use - spinors should not be parallelized for the moment 2351 !if (mpi_enreg%paral_spinor == 1)then 2352 ! call xmpi_sum(dos%fractions,mpi_enreg%comm_spinor,ierr) 2353 !end if 2354 end if 2355 2356 else 2357 ABI_WARNING('only partial_dos==1 or 2 is coded') 2358 end if 2359 2360 !DEBUG 2361 !write(std_out,*) ' m_epjdos%partial_dos_fractions : exit ' 2362 !ENDDEBUG 2363 2364 if (dtset%prtprocar /= 0) close(unit_procar) 2365 2366 call cwtime(cpu,wall,gflops,"stop") 2367 write(msg,'(2(a,f8.2),a)')" partial_dos_fractions: cpu_time: ",cpu,"[s], walltime: ",wall," [s]" 2368 call wrtout(std_out,msg,"PERS") 2369 2370 end subroutine partial_dos_fractions
m_epjdos/partial_dos_fractions_paw [ Functions ]
[ Top ] [ m_epjdos ] [ Functions ]
NAME
partial_dos_fractions_paw
FUNCTION
Calculate PAW contributions to the partial DOS fractions (tetrahedron method)
INPUTS
cprj(natom,mcprj)= <p_lmn|Cnk> coefficients for each WF |Cnk> and each |p_lmn> non-local projector dimcprj(natom)=array of dimensions of array cprj (not ordered) dtset structured datatype, from which one uses : iatsph(nasph)=number of atoms used to project dos kpt(3,nkpt) =irreducible kpoints mband =max number of bands per k-point mkmem =number of kpoints in memory natom =number of atoms in total natsph =number of atoms ofor which the spherical decomposition must be done nband =number of electronic bands for each kpoint nkpt =number of irreducible kpoints nspinor =number of spinor components nsppol =1 or 2 spin polarization channels fatbands_flag =1 if pawfatbnd=1 or 2 mbesslang=maximum angular momentum for Bessel function expansion mpi_enreg=information about MPI parallelization prtdosm=option for the m-contributions to the partial DOS ndosfraction=natsph*mbesslang paw_dos_flag=option for the PAW contributions to the partial DOS pawrad(ntypat) <type(pawrad_type)>=paw radial mesh and related data: pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
OUTPUT
=== If paw_dos_flag==1: dos%fractions_paw1(ikpt,iband,isppol,natom*mbesslang) = contribution to dos fractions from the PAW partial waves (phi) dos%fractions_pawt1(ikpt,iband,isppol,natom*mbesslang) = contribution to dos fractions from the PAW pseudo partial waves (phi_tild)
SIDE EFFECTS
dos%fractions(ikpt,iband,isppol,ndosfraction) = percentage of s, p, d.. character on each atom for the wavefunction # ikpt,iband, isppol As input: contains only the pseudo contribution As output: contains pseudo contribution + PAW corrections == if prtdosm==1 dos%fractions_m(ikpt,iband,isppol,ndosfraction*mbesslang*prtdosm) = m discretization of partial DOS fractions
SOURCE
2421 subroutine partial_dos_fractions_paw(dos,cprj,dimcprj,dtset,mcprj,mkmem,mpi_enreg,pawrad,pawtab) 2422 2423 !Arguments ------------------------------------ 2424 !scalars 2425 integer,intent(in) :: mcprj,mkmem 2426 type(MPI_type),intent(in) :: mpi_enreg 2427 type(dataset_type),intent(in) :: dtset 2428 type(epjdos_t),intent(inout) :: dos 2429 !arrays 2430 integer,intent(in) :: dimcprj(dtset%natom) 2431 type(pawcprj_type),intent(in) :: cprj(dtset%natom,mcprj) 2432 type(pawrad_type),intent(in) :: pawrad(dtset%ntypat) 2433 type(pawtab_type),target,intent(in) :: pawtab(dtset%ntypat) 2434 2435 !Local variables------------------------------- 2436 !scalars 2437 integer :: bandpp,basis_size,comm_kptband,cplex,fatbands_flag,iat,iatom,iband,ibg,ibsp 2438 integer :: ierr,ikpt,il,ilang,ilmn,iln,im,iorder_cprj,ispinor,isppol,itypat,j0lmn,j0ln 2439 integer :: jl,jlmn,jln,jm,klmn,kln,lmn_size,mbesslang,me_band,me_kpt,my_nspinor 2440 integer :: nband_cprj_k,nband_k,ndosfraction,nprocband,nproc_spkptband,paw_dos_flag,prtdosm 2441 real(dp) :: cpij,one_over_nproc 2442 !character(len=500) :: msg 2443 !arrays 2444 integer ,allocatable :: dimcprj_atsph(:) 2445 integer,ABI_CONTIGUOUS pointer :: indlmn(:,:) 2446 real(dp) :: tsec(2) 2447 real(dp),allocatable :: int1(:,:),int2(:,:),int1m2(:,:) 2448 type(pawcprj_type),allocatable :: cprj_k(:,:) 2449 2450 !****************************************************************************************** 2451 2452 DBG_ENTER("COLL") 2453 2454 ABI_CHECK(mkmem/=0,"mkmem==0 not supported anymore!") 2455 2456 fatbands_flag = dos%fatbands_flag 2457 mbesslang = dos%mbesslang 2458 prtdosm = dos%prtdosm 2459 ndosfraction = dos%ndosfraction 2460 paw_dos_flag = dos%paw_dos_flag 2461 2462 !m-decomposed DOS not compatible with PAW-decomposed DOS 2463 if(prtdosm>=1.and.paw_dos_flag==1) then 2464 ABI_ERROR('m-decomposed DOS not compatible with PAW-decomposed DOS!') 2465 end if 2466 2467 !Prepare some useful integrals 2468 basis_size=pawtab(1)%basis_size 2469 if (dtset%ntypat>1) then 2470 do itypat=1,dtset%ntypat 2471 basis_size=max(basis_size,pawtab(itypat)%basis_size) 2472 end do 2473 end if 2474 ABI_MALLOC(int1 ,(basis_size*(basis_size+1)/2,dtset%natsph)) 2475 ABI_MALLOC(int2,(basis_size*(basis_size+1)/2,dtset%natsph)) 2476 ABI_MALLOC(int1m2,(basis_size*(basis_size+1)/2,dtset%natsph)) 2477 int1=zero;int2=zero;int1m2=zero 2478 do iat=1,dtset%natsph 2479 iatom=dtset%iatsph(iat) 2480 itypat= dtset%typat(iatom) 2481 do jln=1,pawtab(itypat)%basis_size 2482 j0ln=jln*(jln-1)/2 2483 do iln=1,jln 2484 kln=j0ln+iln 2485 call simp_gen(int1(kln,iat),pawtab(itypat)%phiphj(:,kln),pawrad(itypat)) 2486 if (dtset%pawprtdos<2) then 2487 call simp_gen(int2(kln,iat),pawtab(itypat)%tphitphj(:,kln),pawrad(itypat)) 2488 int1m2(kln,iat)=int1(kln,iat)-int2(kln,iat) 2489 else 2490 int2(kln,iat)=zero;int1m2(kln,iat)=int1(kln,iat) 2491 end if 2492 end do !iln 2493 end do !jln 2494 end do 2495 2496 !Antiferro case 2497 if (dtset%nspden==2.and.dtset%nsppol==1.and.dtset%nspinor==1) then 2498 int1m2(:,:)=half*int1m2(:,:) 2499 if (paw_dos_flag==1.or.fatbands_flag==1.or.prtdosm==2) then 2500 int1(:,:)=half*int1(:,:);int2(:,:)=half*int2(:,:) 2501 end if 2502 end if 2503 2504 !Init parallelism 2505 comm_kptband=mpi_enreg%comm_kptband 2506 nproc_spkptband=xmpi_comm_size(comm_kptband)*mpi_enreg%nproc_spinor 2507 me_kpt=mpi_enreg%me_kpt ; me_band=mpi_enreg%me_band 2508 my_nspinor=max(1,dtset%nspinor/mpi_enreg%nproc_spinor) 2509 bandpp=1;if (mpi_enreg%paral_kgb==1) bandpp=mpi_enreg%bandpp 2510 !Check if cprj is distributed over bands 2511 nprocband=my_nspinor*dtset%mband*dtset%mkmem*dtset%nsppol/mcprj 2512 if (nprocband/=mpi_enreg%nproc_band) then 2513 ABI_BUG('wrong mcprj/nproc_band!') 2514 end if 2515 2516 !Quick hack: in case of parallelism, dos_fractions have already 2517 ! been reduced over MPI processes; they have to be prepared before 2518 ! the next reduction (at the end of the following loop). 2519 if (nproc_spkptband>1) then 2520 one_over_nproc=one/real(nproc_spkptband,kind=dp) 2521 !$OMP PARALLEL DO COLLAPSE(4) & 2522 !$OMP& DEFAULT(SHARED) PRIVATE(ilang,isppol,iband,ikpt) 2523 do ilang=1,ndosfraction 2524 do isppol=1,dtset%nsppol 2525 do iband=1,dtset%mband 2526 do ikpt=1,dtset%nkpt 2527 dos%fractions(ikpt,iband,isppol,ilang)= & 2528 & one_over_nproc*dos%fractions(ikpt,iband,isppol,ilang) 2529 end do 2530 end do 2531 end do 2532 end do 2533 !$OMP END PARALLEL DO 2534 if (fatbands_flag==1.or.prtdosm==1.or.prtdosm==2) then 2535 !$OMP PARALLEL DO COLLAPSE(4) & 2536 !$OMP& DEFAULT(SHARED) PRIVATE(ilang,isppol,iband,ikpt) 2537 do ilang=1,ndosfraction*mbesslang 2538 do isppol=1,dtset%nsppol 2539 do iband=1,dtset%mband 2540 do ikpt=1,dtset%nkpt 2541 dos%fractions_m(ikpt,iband,isppol,ilang)= & 2542 & one_over_nproc*dos%fractions_m(ikpt,iband,isppol,ilang) 2543 end do 2544 end do 2545 end do 2546 end do 2547 !$OMP END PARALLEL DO 2548 end if 2549 end if 2550 2551 iorder_cprj=0 2552 2553 !LOOPS OVER SPINS,KPTS 2554 ibg=0 2555 do isppol =1,dtset%nsppol 2556 do ikpt=1,dtset%nkpt 2557 2558 nband_k=dtset%nband(ikpt+(isppol-1)*dtset%nkpt) 2559 if (proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,me_kpt)) cycle 2560 2561 cplex=2;if (dtset%istwfk(ikpt)>1) cplex=1 2562 nband_cprj_k=nband_k/nprocband 2563 ABI_MALLOC(cprj_k,(dtset%natsph,my_nspinor*nband_cprj_k)) 2564 ABI_MALLOC(dimcprj_atsph,(dtset%natsph)) 2565 do iat=1,dtset%natsph 2566 dimcprj_atsph(iat)=dimcprj(dtset%iatsph(iat)) 2567 end do 2568 call pawcprj_alloc(cprj_k,0,dimcprj_atsph) 2569 ABI_FREE(dimcprj_atsph) 2570 2571 ! Extract cprj for this k-point. 2572 ibsp=0 2573 do iband=1,nband_cprj_k 2574 do ispinor=1,my_nspinor 2575 ibsp=ibsp+1 2576 do iat=1,dtset%natsph 2577 iatom=dtset%iatsph(iat) 2578 cprj_k(iat,ibsp)%cp(:,:)=cprj(iatom,ibsp+ibg)%cp(:,:) 2579 end do 2580 end do 2581 end do 2582 2583 ! LOOP OVER ATOMS (natsph_extra is not included on purpose) 2584 do iat=1,dtset%natsph 2585 iatom=dtset%iatsph(iat) 2586 itypat= dtset%typat(iatom) 2587 lmn_size=pawtab(itypat)%lmn_size 2588 indlmn => pawtab(itypat)%indlmn 2589 2590 ! LOOP OVER BANDS 2591 ibsp=0 2592 do iband=1,nband_k 2593 2594 if (mod((iband-1)/bandpp,nprocband)/=me_band) cycle 2595 if (proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,iband,iband,isppol,me_kpt)) then 2596 ibsp=ibsp+my_nspinor;cycle 2597 end if 2598 2599 do ispinor=1,my_nspinor 2600 ibsp=ibsp+1 2601 2602 do ilang=1,mbesslang 2603 2604 do jlmn=1,lmn_size 2605 jl=indlmn(1,jlmn) 2606 jm=indlmn(2,jlmn) 2607 j0lmn=jlmn*(jlmn-1)/2 2608 do ilmn=1,jlmn 2609 il=indlmn(1,ilmn) 2610 im=indlmn(2,ilmn) 2611 klmn=j0lmn+ilmn 2612 kln=pawtab(itypat)%indklmn(2,klmn) 2613 2614 if (il==ilang-1.and.jl==ilang-1.and.im==jm) then 2615 2616 cpij=cprj_k(iat,ibsp)%cp(1,ilmn)*cprj_k(iat,ibsp)%cp(1,jlmn) 2617 if (cplex==2) cpij=cpij+cprj_k(iat,ibsp)%cp(2,ilmn)*cprj_k(iat,ibsp)%cp(2,jlmn) 2618 cpij=pawtab(itypat)%dltij(klmn)*cpij 2619 2620 dos%fractions(ikpt,iband,isppol,mbesslang*(iat-1)+ilang)= & 2621 & dos%fractions(ikpt,iband,isppol,mbesslang*(iat-1)+ilang) + & 2622 & cpij*int1m2(kln,iat) 2623 if (prtdosm==1) then 2624 dos%fractions_m(ikpt,iband,isppol,mbesslang**2*(iat-1)+il**2+il+1+im)= & 2625 & dos%fractions_m(ikpt,iband,isppol,mbesslang**2*(iat-1)+il**2+il+1+im) + & 2626 & cpij*int1m2(kln,iat) 2627 end if 2628 if (fatbands_flag==1.or.prtdosm==2) then 2629 dos%fractions_m(ikpt,iband,isppol,mbesslang**2*(iat-1)+il**2+il+1+im)= & 2630 & dos%fractions_m(ikpt,iband,isppol,mbesslang**2*(iat-1)+il**2+il+1+im) + & 2631 & cpij*int1(kln,iat) 2632 end if 2633 if (paw_dos_flag==1) then 2634 dos%fractions_paw1(ikpt,iband,isppol,mbesslang*(iat-1)+ilang)= & 2635 & dos%fractions_paw1(ikpt,iband,isppol,mbesslang*(iat-1)+ilang) + & 2636 & cpij*int1(kln,iat) 2637 dos%fractions_pawt1(ikpt,iband,isppol,mbesslang*(iat-1)+ilang)= & 2638 & dos%fractions_pawt1(ikpt,iband,isppol,mbesslang*(iat-1)+ilang) + & 2639 & cpij*int2(kln,iat) 2640 end if 2641 2642 end if 2643 2644 end do !ilmn 2645 end do !jlmn 2646 2647 end do ! ilang 2648 end do ! ispinor 2649 end do ! iband 2650 2651 end do !iatom 2652 2653 if (mkmem/=0) ibg = ibg + my_nspinor*nband_cprj_k 2654 call pawcprj_free(cprj_k) 2655 ABI_FREE(cprj_k) 2656 end do ! ikpt 2657 end do ! isppol 2658 2659 ABI_FREE(int1) 2660 ABI_FREE(int2) 2661 ABI_FREE(int1m2) 2662 2663 !Reduce data in case of parallelism 2664 call timab(48,1,tsec) 2665 call xmpi_sum(dos%fractions,comm_kptband,ierr) 2666 if (prtdosm>=1.or.fatbands_flag==1) then 2667 call xmpi_sum(dos%fractions_m,comm_kptband,ierr) 2668 end if 2669 if (paw_dos_flag==1) then 2670 call xmpi_sum(dos%fractions_paw1,comm_kptband,ierr) 2671 call xmpi_sum(dos%fractions_pawt1,comm_kptband,ierr) 2672 end if 2673 call timab(48,2,tsec) 2674 if (mpi_enreg%paral_spinor==1) then 2675 call xmpi_sum(dos%fractions,mpi_enreg%comm_spinor,ierr) 2676 if (prtdosm>=1.or.fatbands_flag==1) then 2677 call xmpi_sum(dos%fractions_m,mpi_enreg%comm_spinor,ierr) 2678 end if 2679 if (paw_dos_flag==1) then 2680 call xmpi_sum(dos%fractions_paw1, mpi_enreg%comm_spinor,ierr) 2681 call xmpi_sum(dos%fractions_pawt1, mpi_enreg%comm_spinor,ierr) 2682 end if 2683 end if 2684 2685 !Averaging: A quick hack for m-decomposed LDOS: 2686 !BA: not valid in presence of spin-orbit coupling ! 2687 if (prtdosm==1.and.fatbands_flag==0) then 2688 ! if pawfatbnd is activated, one think in the cubic harmonics basis 2689 ! whereas prtdosm=1 is in the spherical harmonics basis. 2690 ! the following trick is done in order to have everything 2691 ! in the complex spherical basis (not useful for pawfatbnd if we want to 2692 ! have e.g t2g and eg d-orbitals). 2693 do iat=1,dtset%natsph 2694 do il = 0, mbesslang-1 2695 do im = 1, il 2696 dos%fractions_m(:,:,:,mbesslang**2*(iat-1)+il**2+il+1+im) = & 2697 & (dos%fractions_m(:,:,:,mbesslang**2*(iat-1)+il**2+il+1+im) + & 2698 & dos%fractions_m(:,:,:,mbesslang**2*(iat-1)+il**2+il+1-im))/2 2699 dos%fractions_m(:,:,:,mbesslang**2*(iat-1)+il**2+il+1-im) = & 2700 & dos%fractions_m(:,:,:,mbesslang**2*(iat-1)+il**2+il+1+im) 2701 end do 2702 end do 2703 end do !iatom 2704 end if 2705 2706 DBG_EXIT("COLL") 2707 2708 end subroutine partial_dos_fractions_paw
m_epjdos/prtfatbands [ Functions ]
[ Top ] [ m_epjdos ] [ Functions ]
NAME
prtfatbands
FUNCTION
Print dos_fractions_m in order to plot easily fatbands if pawfatbnd=1 1 : fatbands are resolved in L. if pawfatbnd=1 2 : fatbands are resolved in L and M.
INPUTS
dos_fractions_m(nkpt,mband,nsppol,ndosfraction*mbesslang*m_dos_flag) = m-resolved projected dos inside PAW sphere. dtset = Input variables ebands<ebands_t>=Band structure data. pawfatbnd = keyword for fatbands mbesslang =maximum angular momentum for Bessel function expansion m_dos_flag =option for the m-contributions to the partial DOS ndosfraction =natsph*mbesslang
OUTPUT
(only writing)
NOTES
This routine should be called by master only
SOURCE
1488 subroutine prtfatbands(dos,dtset,ebands,fildata,pawfatbnd,pawtab) 1489 1490 !Arguments ------------------------------------ 1491 !scalars 1492 integer,intent(in) :: pawfatbnd 1493 type(epjdos_t),intent(in) :: dos 1494 type(ebands_t),intent(in) :: ebands 1495 type(dataset_type),intent(in) :: dtset 1496 character(len=fnlen),intent(in) :: fildata 1497 !arrays 1498 type(pawtab_type),intent(in) :: pawtab(dtset%ntypat) 1499 1500 !Local variables------------------------------- 1501 !scalars 1502 integer :: iall,il,iat,natsph,inbfatbands,iband,mband,ixfat,isppol,nkpt,lmax,ll,mm 1503 integer :: ikpt,nband_k,ndosfraction,mbesslang 1504 real(dp) :: xfatband,cpu,wall,gflops 1505 character(len=1) :: tag_l,tag_1m,tag_is 1506 character(len=2) :: tag_2m 1507 character(len=10) :: tag_il,tag_at,tag_grace 1508 character(len=1500) :: msg 1509 character(len=fnlen) :: tmpfil 1510 type(atomdata_t) :: atom 1511 !arrays 1512 integer,allocatable :: unitfatbands_arr(:,:) 1513 real(dp),allocatable :: eigenvalues(:,:,:) 1514 character(len=2) :: symbol 1515 1516 !************************************************************************* 1517 1518 DBG_ENTER("COLL") 1519 1520 ndosfraction = dos%ndosfraction; mbesslang = dos%mbesslang 1521 1522 if(dos%prtdosm.ne.0) then 1523 write(msg,'(3a)')& 1524 'm decomposed dos is activated',ch10, & 1525 'Action: deactivate it with prtdosm=0 !' 1526 ABI_ERROR(msg) 1527 end if 1528 1529 if(dtset%nspinor==2) then 1530 ABI_WARNING("Fatbands are not yet available in the case nspinor==2!") 1531 end if 1532 1533 ABI_CHECK(allocated(dos%fractions_m), "dos%fractions_m is not allocated!") 1534 1535 natsph=dtset%natsph 1536 nkpt=dtset%nkpt 1537 mband=dtset%mband 1538 1539 if(natsph>1000) then 1540 write(msg,'(3a)')& 1541 'Too big number of fat bands!',ch10, & 1542 'Action: decrease natsph in input file !' 1543 ABI_ERROR(msg) 1544 end if 1545 1546 !-------------- PRINTING IN LOG 1547 call cwtime(cpu, wall, gflops, "start") 1548 write(msg,'(a,a,a,a,i5,a,a,1000i5)') ch10," ***** Print of fatbands activated ****** ",ch10,& 1549 " Number of atom: natsph = ",natsph,ch10, & 1550 " atoms are = ",(dtset%iatsph(iat),iat=1,natsph) 1551 call wrtout(std_out,msg,'COLL') 1552 call wrtout(ab_out,msg,'COLL') 1553 iall=0;inbfatbands=0 1554 1555 if(pawfatbnd==1) then 1556 inbfatbands=mbesslang-1 1557 write(msg,'(3a)')" (fatbands are in eV and are given for each value of L)",ch10 1558 else if(pawfatbnd==2) then 1559 write(msg,'(3a)')" (fatbands are in eV and are given for each value of L and M)",ch10 1560 inbfatbands=(mbesslang-1)**2 1561 end if 1562 call wrtout(std_out,msg,'COLL') 1563 call wrtout(ab_out,msg,'COLL') 1564 1565 write(msg,'(a,e12.5,a,e12.5,a)') " Fermi energy is ",ebands%fermie*Ha_eV," eV = ",ebands%fermie," Ha" 1566 call wrtout(std_out,msg,'COLL') 1567 1568 !-------------- OPEN AND NAME FILES FOR FATBANDS 1569 ABI_MALLOC(unitfatbands_arr,(natsph*inbfatbands,dtset%nsppol)) 1570 unitfatbands_arr = -3 1571 1572 do iat=1,natsph 1573 lmax=(pawtab(dtset%typat(dtset%iatsph(iat)))%l_size-1)/2 1574 call int2char4(dtset%iatsph(iat),tag_at) 1575 ABI_CHECK((tag_at(1:1)/='#'),'Bug: string length too short!') 1576 call atomdata_from_znucl(atom,dtset%znucl(dtset%typat(dtset%iatsph(iat)))) 1577 symbol = atom%symbol 1578 do il=1,inbfatbands 1579 iall=iall+1 1580 ll=int(sqrt(float(il-1))) ! compute l 1581 if(ll.le.lmax) then ! print only angular momentum included in the PAW data 1582 do isppol=1,dtset%nsppol 1583 write(tag_is,'(i1)')isppol 1584 if(pawfatbnd==1) then 1585 call int2char4(il-1,tag_il) 1586 ABI_CHECK((tag_il(1:1)/='#'),'Bug: string length too short!') 1587 tmpfil = trim(fildata)//'_at'//trim(tag_at)//'_'//trim(adjustl(symbol))//'_is'//tag_is//'_l'//trim(tag_il) 1588 else if (pawfatbnd==2) then 1589 write(tag_l,'(i1)') ll 1590 mm=il-(ll**2+ll+1) ! compute m 1591 if(mm<0) write(tag_2m,'(i2)') mm 1592 if(mm>=0) write(tag_1m,'(i1)') mm 1593 if(mm<0) tmpfil = trim(fildata)// & 1594 & '_at'//trim(tag_at)//'_'//trim(adjustl(symbol))//'_is'//tag_is//'_l'//tag_l//'_m'//tag_2m 1595 if(mm>=0) tmpfil = trim(fildata)// & 1596 & '_at'//trim(tag_at)//'_'//trim(adjustl(symbol))//'_is'//tag_is//'_l'//tag_l//'_m+'//tag_1m 1597 end if 1598 !unitfatbands_arr(iall,isppol)=tmp_unit+100+iall-1+(natsph*inbfatbands)*(isppol-1) 1599 !open (unit=unitfatbands_arr(iall,isppol),file=trim(tmpfil),status='unknown',form='formatted') 1600 if (open_file(tmpfil, msg, newunit=unitfatbands_arr(iall,isppol), status='unknown',form='formatted') /= 0) then 1601 ABI_ERROR(msg) 1602 end if 1603 1604 write(msg,'(a,a,a,i4)') 'opened file : ', trim(tmpfil), ' unit', unitfatbands_arr(iall,isppol) 1605 call wrtout(std_out,msg,'COLL') 1606 write(msg,'(9a)') "# ",ch10,"# ABINIT package : FATBAND file ", ch10,& 1607 "# It contains, for each band: the eigenvalues in eV (and the character of the band) as a function of the k-point",& 1608 ch10,"# This file can be read with xmgrace (http://plasma-gate.weizmann.ac.il/Grace/) ",ch10,"# " 1609 write(unitfatbands_arr(iall,isppol), "(a)")trim(msg) 1610 do iband=1,mband 1611 call int2char4(iband-1,tag_grace) 1612 ABI_CHECK((tag_grace(1:1)/='#'),'Bug: string length too short!') 1613 write(msg,'(16a)') ch10,"@ s",trim(tag_grace)," line color 1",& 1614 ch10,"@ s",trim(tag_grace)," errorbar color 2",& 1615 ch10,"@ s",trim(tag_grace)," errorbar riser linewidth 5.0", & 1616 ch10,"@ s",trim(tag_grace)," errorbar linestyle 0" 1617 write(unitfatbands_arr(iall,isppol), "(a)")trim(msg) 1618 end do !iband 1619 write(unitfatbands_arr(iall,isppol), '(a,a)') ch10,'@type xydy' 1620 end do ! isppol 1621 end if ! ll=<lmax 1622 end do ! il 1623 end do ! iat 1624 1625 if(iall.ne.(natsph*inbfatbands)) then 1626 ABI_ERROR("error1 ") 1627 end if 1628 1629 1630 1631 !-------------- WRITE FATBANDS IN FILES 1632 if (pawfatbnd>0) then 1633 ! Store eigenvalues with nkpt as first dimension for efficiency reasons 1634 ABI_MALLOC(eigenvalues,(nkpt,mband,dtset%nsppol)) 1635 do isppol=1,dtset%nsppol 1636 do ikpt=1,nkpt 1637 nband_k=dtset%nband(ikpt+(isppol-1)*nkpt) 1638 do iband=1,mband 1639 eigenvalues(ikpt,iband,isppol)= ebands%eig(iband, ikpt, isppol) - ebands%fermie 1640 end do 1641 end do 1642 end do 1643 iall=0 1644 do iat=1,natsph 1645 lmax=(pawtab(dtset%typat(dtset%iatsph(iat)))%l_size-1)/2 1646 do il=1,inbfatbands 1647 iall=iall+1 1648 ll=int(sqrt(float(il-1))) 1649 if(ll.le.lmax) then 1650 do isppol=1,dtset%nsppol 1651 do iband=1,mband 1652 write(unitfatbands_arr(iall,isppol),'(a,a,i8)') ch10,"# BAND number :",iband 1653 do ikpt=1,nkpt 1654 if(pawfatbnd==1) then 1655 xfatband=0.d0 1656 do ixfat=(il-1)**2+1,il**2 1657 xfatband=xfatband+dos%fractions_m(ikpt,iband,isppol,(iat-1)*mbesslang**2+ixfat) 1658 end do ! ixfat 1659 else if (pawfatbnd==2) then 1660 xfatband=dos%fractions_m(ikpt,iband,isppol,(iat-1)*mbesslang**2+il) 1661 end if 1662 write(unitfatbands_arr(iall,isppol),'(i5,e20.5,e20.5)')& 1663 ikpt-1,eigenvalues(ikpt,iband,isppol)*Ha_eV,xfatband 1664 end do ! ikpt 1665 end do !iband 1666 write(unitfatbands_arr(iall,isppol),'(a)') '&' 1667 !close(unitfatbands_arr(iall,isppol)) 1668 end do !isppol 1669 end if 1670 end do ! il 1671 end do ! iat 1672 ABI_FREE(eigenvalues) 1673 end if 1674 1675 do isppol=1,size(unitfatbands_arr, dim=2) 1676 do iat=1,size(unitfatbands_arr, dim=1) 1677 if (unitfatbands_arr(iat, isppol) /= -3) close (unitfatbands_arr(iat, isppol)) 1678 end do 1679 end do 1680 1681 ABI_FREE(unitfatbands_arr) 1682 1683 call cwtime(cpu,wall,gflops,"stop") 1684 write(msg,'(2(a,f8.2),a)')" prtfatbands: cpu_time: ",cpu,"[s], walltime: ",wall," [s]" 1685 call wrtout(std_out,msg,"PERS") 1686 1687 DBG_EXIT("COLL") 1688 1689 end subroutine prtfatbands
m_epjdos/recip_ylm [ Functions ]
[ Top ] [ m_epjdos ] [ Functions ]
NAME
recip_ylm
FUNCTION
Project input wavefunctions in reciprocal space on to Ylm (real or complex harmonics depending on rc_ylm).
INPUTS
bess_fit(mpw,nradintmax,ll) = Bessel functions for L, splined with arguments $2 \pi |k+G| \Delta r$, for all G vectors in sphere and all points on radial grid. cg_1band(2,npw_k)=wavefunction in recip space (note that nspinor is missing, see Notes). istwfk= storage mode of cg_1band nradint(natsph)=number of points on radial real-space grid for a given atom. nradintmax=dimension of rint array. me_g0=1 if this processor has G=0, 0 otherwise mlang=maximum angular momentum in Bessel functions. mpw=Maximum number of planewaves. Used to dimension bess_fit natsph=number of atoms around which ang mom projection has to be done typat_extra(natsph)=Type of each atom. ntypat + 1 if empty sphere mlang_type(ntypat + natsph_extra)=Max L+1 for each atom type npw_k=number of plane waves for this kpt nspinor=number of spinor components ph3d(2,npw_k,natsph)=3-dim structure factors, for each atom and plane wave. prtsphere= if 1, print a complete analysis of the angular momenta in atomic spheres rint(nradintmax) = points on radial real-space grid for integration rmax(natsph)=maximum radius for real space integration sphere rc_ylm= 1 for real spherical harmonics. 2 for complex spherical harmonics, ucvol=unit cell volume in bohr**3. ylm_k(npw_k,mlang**2)=real spherical harmonics for each G and LM. znucl_sph(natsph)=gives the nuclear number for each type of atom
OUTPUT
sum_1ll_1atom(mlang,natsph)= projected scalars for each atom and ang. mom. sum_1lm_1atom(mlang*mlang,natsph)= projected scalars for each atom and LM component. cplx_1lm_1atom(2,dtset%nspinor**2,dos%mbesslang**2,natsph_tot) = complex projection of wave function on atomic like orbital
NOTES
* ph3d atoms are ordered with natsph and must be provided by the caller in the correct order! * spinor components are not treated here. This facilitates the implementation of spinor parallelism because the caller can easily call the routine inside a loop over spinors and then sum the different contributions outside the loop thus reducing the number of MPI calls.
SOURCE
886 subroutine recip_ylm (bess_fit, cg_1band, istwfk, mpi_enreg, nradint, nradintmax, mlang,& 887 & mpw, natsph, typat_extra, mlang_type, npw_k, nspinor, ph3d, prtsphere, rint, rmax,& 888 & rc_ylm, sum_1ll_1atom, sum_1lm_1atom, cplx_1lm_1atom, ucvol, ylm_k, znucl_sph) 889 890 !Arguments ------------------------------------ 891 !scalars 892 integer,intent(in) :: istwfk,mlang,mpw,natsph,npw_k,nradintmax 893 integer,intent(in) :: nspinor 894 integer,intent(in) :: prtsphere,rc_ylm 895 real(dp),intent(in) :: ucvol 896 !arrays 897 integer,intent(in) :: nradint(natsph),typat_extra(natsph),mlang_type(:) 898 real(dp),intent(in) :: bess_fit(mpw,nradintmax,mlang),cg_1band(:,:) !(2,my_nspinor*npw_k) 899 real(dp),intent(in) :: ph3d(2,npw_k,natsph),rint(nradintmax) 900 real(dp),intent(in) :: rmax(natsph),ylm_k(npw_k,mlang*mlang) 901 real(dp),intent(in) :: znucl_sph(natsph) 902 type(MPI_type),intent(in) :: mpi_enreg 903 real(dp),intent(out) :: sum_1ll_1atom(nspinor**2, mlang, natsph) 904 real(dp),intent(out) :: sum_1lm_1atom(nspinor**2, mlang*mlang,natsph) 905 real(dp),intent(out) :: cplx_1lm_1atom(2,nspinor, mlang*mlang,natsph) 906 907 !Local variables------------------------------- 908 !scalars 909 integer :: ilm,iat,ipw,ixint,ll,mm,il,jlm,ierr,lm_size,itypat 910 integer :: ispinor 911 integer :: ipauli, is, isp 912 integer :: my_nspinor 913 real(dp),parameter :: invsqrt2=one/sqrt2 914 real(dp) :: sum_all, dr, fact 915 type(atomdata_t) :: atom 916 character(len=500) :: msg 917 !arrays 918 integer :: ilang(mlang**2) 919 real(dp) :: c1(2),c2(2) 920 real(dp) :: sum_1atom(natsph),sum_1ll(mlang),sum_1lm(mlang**2) 921 real(dp) :: func(nradintmax) 922 real(dp) :: func_cplx(nradintmax,2) 923 complex(dpc) :: vect(npw_k) 924 complex(dpc),allocatable :: tmppsia(:,:),tmppsim(:,:),dotc(:) 925 integer, allocatable :: ispinors(:) 926 complex(dpc),allocatable :: values(:,:,:,:) 927 928 ! ************************************************************************* 929 930 ! Workspace array (used to reduce the number of MPI communications) 931 ! One could reduce a bit the memory requirement by using non-blocking operations ... 932 ABI_MALLOC_OR_DIE(values, (nradintmax, nspinor, mlang**2, natsph), ierr) 933 values = czero 934 935 my_nspinor = max(1,nspinor/mpi_enreg%nproc_spinor) 936 ABI_MALLOC(tmppsia, (npw_k,my_nspinor)) 937 ABI_MALLOC(tmppsim, (npw_k,my_nspinor)) 938 ABI_MALLOC(dotc, (my_nspinor)) 939 ABI_MALLOC(ispinors, (my_nspinor)) 940 if (my_nspinor == 2) then 941 ispinors(1) = 1 942 ispinors(2) = 2 943 else 944 ispinors(1) = mpi_enreg%me_spinor+1 945 end if 946 947 sum_1lm_1atom = zero 948 cplx_1lm_1atom = zero 949 950 do ll=0,mlang-1 951 do mm=-ll,ll 952 ilm = (ll+1)**2-ll+mm 953 ilang(ilm) = ll+1 954 end do 955 end do 956 957 ! Big loop on all atoms 958 do iat=1,natsph 959 itypat = typat_extra(iat) 960 lm_size = mlang_type(itypat) ** 2 961 dr = rmax(iat) / (nradint(iat)-1) 962 963 ! u(G) e^{i(k+G).Ra} 964 ! tmppsia = Temporary array for part which depends only on iat 965 do ispinor=1,my_nspinor 966 do ipw=1,npw_k 967 tmppsia(ipw,ispinor) = dcmplx(cg_1band(1,ipw+(ispinor-1)*npw_k),cg_1band(2,ipw+(ispinor-1)*npw_k)) & 968 & * dcmplx(ph3d(1,ipw,iat), ph3d(2,ipw,iat)) 969 end do 970 end do 971 972 ! tmppsim = temporary arrays for part of psi which does not depend on ixint = tmppsia * ylm. 973 ! could remove this intermediate array to save memory... 974 ! u(G) Y_LM^*(k+G) e^{i(k+G).Ra} 975 ! Take into account the fact that ylm_k are REAL spherical harmonics, see initylmg.f 976 ! For time-reversal states, detailed treatment show that only the real or imaginary 977 ! part of tmppsia is needed here, depending on l being even or odd: only one of the coef is 1, the other 0 978 do ilm=1,lm_size 979 il = ilang(ilm) 980 ll = ilang(ilm) - 1 981 mm = ilm - (ll+1)**2 + ll 982 983 select case (rc_ylm) 984 case (1) 985 ! to get PDOS for real spherical harmonics, simply multiply here by ylm_k 986 do ispinor=1,my_nspinor 987 do ipw=1,npw_k 988 tmppsim(ipw,ispinor) = tmppsia(ipw,ispinor) * ylm_k(ipw,ilm) 989 end do 990 end do 991 992 ! Handle time-reversal 993 ! TODO: check if time reversal with spinors is special and may need some treatment. 994 ! normally SOC will simply impose istwfk 1 in appropriate cases (kptopt 4). 995 if (istwfk /= 1) then 996 if (mod(ll, 2) == 0) then 997 tmppsim(:,:) = dcmplx(real(tmppsim(:,:)),zero) 998 else 999 tmppsim(:,:) = dcmplx(aimag(tmppsim(:,:)),zero) 1000 end if 1001 ! f2008 version: 1002 ! if (mod(ll, 2) == 0) then 1003 ! tmppsim(:,:)%im = zero 1004 ! else 1005 ! tmppsim(:,:)%re = tmppsim(:,:)%im 1006 ! tmppsim(:,:)%im = zero 1007 ! end if 1008 end if 1009 1010 case (2) 1011 ! to get PDOS for complex spherical harmonics, build linear combination of real ylm_k 1012 jlm = (ll+1)**2-ll-mm ! index of (l, -m) 1013 if (mm == 0) then 1014 vect(:) = dcmplx(ylm_k(1:npw_k,ilm),zero) 1015 else if (mm > 0) then 1016 !vect(1,:) = invsqrt2 * ylm_k(1:npw_k,ilm) * (-1)**mm 1017 !vect(2,:) = +invsqrt2 * ylm_k(1:npw_k,jlm) * (-1)**mm 1018 c1 = sy(ll, mm, mm) 1019 c2 = sy(ll,-mm, mm) 1020 vect(:) = dcmplx(c1(1) * ylm_k(1:npw_k,ilm) + c2(1) * ylm_k(1:npw_k,jlm), & 1021 c1(2) * ylm_k(1:npw_k,ilm) + c2(2) * ylm_k(1:npw_k,jlm)) 1022 1023 else if (mm < 0) then 1024 !vect(1,:) = invsqrt2 * ylm_k(1:npw_k,jlm) !* (-1)**mm 1025 !vect(2,:) = -invsqrt2 * ylm_k(1:npw_k,ilm) !* (-1)**mm 1026 c1 = sy(ll, mm, mm) 1027 c2 = sy(ll,-mm, mm) 1028 vect(:) = dcmplx(c1(1) * ylm_k(1:npw_k,ilm) + c2(1) * ylm_k(1:npw_k,jlm),& 1029 c1(2) * ylm_k(1:npw_k,ilm) + c2(2) * ylm_k(1:npw_k,jlm)) 1030 end if 1031 vect(:) = dcmplx(real(vect(:)), -aimag(vect(:))) 1032 !vect(:)%im = -vect(:)%im 1033 1034 if (istwfk == 1) then 1035 do ispinor=1,my_nspinor 1036 do ipw=1,npw_k 1037 tmppsim(ipw,ispinor) = tmppsia(ipw,ispinor) * vect(ipw) 1038 end do 1039 end do 1040 else 1041 ! Handle time-reversal 1042 if (mod(ll, 2) == 0) then 1043 do ispinor=1,my_nspinor 1044 do ipw=1,npw_k 1045 tmppsim(ipw,ispinor) = real(tmppsia(ipw,ispinor)) * vect(ipw) 1046 end do 1047 end do 1048 else 1049 do ispinor=1,my_nspinor 1050 do ipw=1,npw_k 1051 tmppsim(ipw,ispinor) = aimag(tmppsia(ipw,ispinor)) * vect(ipw) 1052 end do 1053 end do 1054 end if 1055 end if 1056 1057 case default 1058 ABI_ERROR("Wrong value for rc_ylm") 1059 end select 1060 1061 ! Compute integral $ \int_0^{rc} dr r**2 ||\sum_G u(G) Y_LM^*(k+G) e^{i(k+G).Ra} j_L(|k+G| r)||**2 $ 1062 ! or more general spinor case integral 1063 ! $ \int_0^{rc} dr r**2 dotc^*_s \sigma^x_{ss'} dotc_{s'} 1064 ! where dotc_s = \sum_G u_s (G) Y_LM^*(k+G) e^{i(k+G).Ra} j_L(|k+G| r) 1065 do ixint=1,nradint(iat) 1066 dotc = czero 1067 do ispinor=1, my_nspinor 1068 do ipw=1,npw_k 1069 dotc(ispinor) = dotc(ispinor) + bess_fit(ipw, ixint, il) * tmppsim(ipw, ispinor) 1070 end do 1071 end do 1072 if (istwfk /= 1) then 1073 dotc = two * dotc 1074 if (istwfk == 2 .and. mpi_enreg%me_g0 == 1) then 1075 dotc(:) = dotc(:) - bess_fit(1, ixint, il) * tmppsim(1, :) 1076 end if 1077 end if 1078 1079 ! Store results to reduce number of xmpi_sum calls if MPI 1080 do ispinor=1, my_nspinor 1081 values(ixint, ispinors(ispinor), ilm, iat) = dotc(ispinor) 1082 end do 1083 end do ! ixint 1084 1085 end do ! ilm 1086 end do ! iat 1087 1088 ABI_FREE(tmppsia) 1089 ABI_FREE(tmppsim) 1090 ABI_FREE(dotc) 1091 ABI_FREE(ispinors) 1092 1093 ! Collect results in comm_pw (data are distributed over plane waves) 1094 call xmpi_sum(values, mpi_enreg%comm_bandfft, ierr) 1095 ! ! Collect results in mpi_enreg%comm_spinor (data are distributed over spinor components) 1096 call xmpi_sum(values, mpi_enreg%comm_spinor, ierr) 1097 1098 ! Multiply by r**2 and take norm, integrate 1099 do iat=1,natsph 1100 itypat = typat_extra(iat) 1101 lm_size = mlang_type(itypat) ** 2 1102 do ilm=1,lm_size 1103 1104 do ipauli=0,nspinor**2-1 1105 do ixint=1,nradint(iat) 1106 func(ixint) = zero 1107 do is=1,nspinor 1108 do isp=1,nspinor 1109 func(ixint) = func(ixint) + real(conjg(values(ixint, is, ilm, iat)) * pauli_mat(is,isp,ipauli)*& 1110 & values(ixint, isp, ilm, iat)) 1111 end do 1112 end do 1113 func(ixint) = rint(ixint)**2 * func(ixint) 1114 end do 1115 ! Here I should treat the case in which the last point /= rcut 1116 ! NB: indexing is from 1 not 0 for spin matrix components 1117 sum_1lm_1atom (ipauli+1, ilm, iat) = simpson(dr, func(1:nradint(iat))) 1118 end do ! ipauli 1119 1120 do is = 1, nspinor 1121 func_cplx(:,1) = real(values(:, is, ilm, iat)) 1122 func_cplx(:,2) = aimag(values(:, is, ilm, iat)) 1123 do ixint=1,nradint(iat) 1124 func_cplx(ixint,:) = rint(ixint)**2 * func_cplx(ixint,:) 1125 end do 1126 cplx_1lm_1atom(1, is, ilm, iat) = simpson(dr, func_cplx(1:nradint(iat),1)) 1127 cplx_1lm_1atom(2, is, ilm, iat) = simpson(dr, func_cplx(1:nradint(iat),2)) 1128 end do 1129 1130 end do ! ilm 1131 end do ! iat 1132 1133 ! Normalize with unit cell volume and include 4pi term coming from Rayleigh expansion. 1134 fact = four_pi**2 / ucvol 1135 sum_1lm_1atom = fact * sum_1lm_1atom 1136 cplx_1lm_1atom = fact * cplx_1lm_1atom 1137 1138 ! sum up the m-independent fractions 1139 sum_1ll_1atom = zero 1140 do iat=1,natsph 1141 itypat = typat_extra(iat) 1142 lm_size = mlang_type(itypat) ** 2 1143 do ilm=1,lm_size 1144 il = ilang(ilm) 1145 sum_1ll_1atom(:,il, iat) = sum_1ll_1atom(:,il, iat) + sum_1lm_1atom(:,ilm, iat) 1146 end do 1147 end do 1148 1149 ABI_FREE(values) 1150 1151 ! Output 1152 if (prtsphere == 1) then 1153 sum_1ll = zero 1154 sum_1lm = zero 1155 sum_1atom = zero 1156 do iat=1,natsph 1157 sum_1atom(iat) = sum(sum_1lm_1atom(1,:,iat)) 1158 sum_1ll(:)=sum_1ll(:)+sum_1ll_1atom(1,:,iat) 1159 sum_1lm(:)=sum_1lm(:)+sum_1lm_1atom(1,:,iat) 1160 end do 1161 sum_all = sum(sum_1atom) 1162 1163 if (rc_ylm == 1) msg = " Angular analysis (real spherical harmonics)" 1164 if (rc_ylm == 2) msg = " Angular analysis (complex spherical harmonics)" 1165 call wrtout(std_out, msg) 1166 do iat=1,natsph 1167 call atomdata_from_znucl(atom, znucl_sph(iat)) 1168 call wrtout(std_out, " ") 1169 write(msg,'(a,i3,a,a,a,f10.6)' )' Atom # ',iat, ' is ', atom%symbol,', in-sphere charge =',sum_1atom(iat) 1170 call wrtout(std_out, msg) 1171 do ll=0,mlang-1 1172 write(msg,'(a,i1,a,f9.6,a,9f6.3)' )& 1173 ' l=',ll,', charge=',sum_1ll_1atom(1,ll+1,iat),& 1174 ', m=-l,l splitting:',sum_1lm_1atom(1,1+ll**2:(ll+1)**2,iat) 1175 call wrtout(std_out, msg) 1176 end do ! ll 1177 end do ! iat 1178 write(msg,'(a,a)') ch10,' Sum of angular contributions for all atomic spheres ' 1179 call wrtout(std_out, msg) 1180 do ll=0,mlang-1 1181 write(msg,'(a,i1,a,f9.6,a,f9.6)' )& 1182 ' l=',ll,', charge =',sum_1ll(ll+1),' proportion =',sum_1ll(ll+1)/sum_all 1183 call wrtout(std_out, msg) 1184 end do 1185 write(msg,'(a,a,f10.6)' ) ch10,' Total over all atoms and l=0 to 4 :',sum_all 1186 call wrtout(std_out, msg) 1187 call wrtout(std_out, " ") 1188 end if 1189 1190 contains 1191 1192 function sy(ll, mm, mp) 1193 use m_paw_sphharm, only : ys 1194 ! Computes the matrix element <Slm|Ylm'> 1195 integer,intent(in) :: ll,mm, mp 1196 1197 real(dp) :: sy(2) 1198 complex(dpc) :: ys_val 1199 1200 ! Computes the matrix element <Yl'm'|Slm> 1201 call ys(ll,mp,ll,mm,ys_val) 1202 !call ys(ll,mm,ll,mp,ys_val) 1203 sy(1) = real(ys_val) 1204 sy(2) = -aimag(ys_val) 1205 1206 end function sy 1207 1208 end subroutine recip_ylm
m_epjdos/sphericaldens [ Functions ]
[ Top ] [ m_epjdos ] [ Functions ]
NAME
sphericaldens
FUNCTION
Compute the convolution of a function with the unity constant function over a sphere of radius rmax . The function is to be given in reciprocal space, the resulting function is also given in reciprocal space. The routine needs the norm of the reciprocal space vectors. The resulting function in reciprocal space can give the integral of the density in any sphere of that radius, centered on any point, by a simple scalar product.
INPUTS
fofg(2,nfft)=initial function, in reciprocal space gnorm(nfft)=norm of the reciprocal space vectors nfft=(effective) number of FFT grid points (for this processor) rmax=radius of the sphere
OUTPUT
sphfofg(2,nfft)=convoluted function, in reciprocal space
SOURCE
1426 subroutine sphericaldens(fofg,gnorm,nfft,rmax,sphfofg) 1427 1428 !Arguments ------------------------------------ 1429 !scalars 1430 integer,intent(in) :: nfft 1431 real(dp),intent(in) :: rmax 1432 !arrays 1433 real(dp),intent(in) :: fofg(2,nfft),gnorm(nfft) 1434 real(dp),intent(out) :: sphfofg(2,nfft) 1435 1436 !Local variables------------------------------- 1437 !scalars 1438 integer :: ifft 1439 real(dp) :: factor,int0yy,rmax_2pi,yy 1440 1441 ! ************************************************************************* 1442 1443 rmax_2pi=two_pi*rmax 1444 factor=four_pi/(two_pi)**3 1445 1446 do ifft=1,nfft 1447 if(abs(gnorm(ifft)) < tol12)then 1448 sphfofg(1,ifft)=fofg(1,ifft)*four_pi*third*rmax**3 1449 sphfofg(2,ifft)=fofg(2,ifft)*four_pi*third*rmax**3 1450 else 1451 yy=gnorm(ifft)*rmax_2pi 1452 int0yy=factor*(sin(yy)-yy*cos(yy))/(gnorm(ifft)**3) 1453 sphfofg(1,ifft)=fofg(1,ifft)*int0yy 1454 sphfofg(2,ifft)=fofg(2,ifft)*int0yy 1455 end if 1456 end do 1457 1458 end subroutine sphericaldens