5
5
! or http://www.gnu.org/copyleft/gpl.txt.
6
6
! See Docs/Contributors.txt for a list of contributors.
8
subroutine mulliken(iopt,nspin,natoms,nbasistot,maxnh,numh,
8
subroutine mulliken(iopt,natoms,nbasistot,maxnh,numh,
9
9
. listhptr,listh,s,dm,isa,lasto,iaorb,
11
11
C ********************************************************************
23
23
C integer iopt : Work option: 1 = atomic and orbital charges
24
24
C 2 = 1 + atomic overlap pop.
25
25
C 3 = 2 + orbital overlap pop.
26
C integer nspin : Number of spin components
27
26
C integer natoms : Number of atoms
28
27
C integer nbasistot : Number of basis orbitals over all nodes
29
28
C integer maxnh : First dimension of d.m. and overlap, and its
32
31
C integer listhptr(nbasis) : Second Control vector of d.m. and overlap
33
32
C integer listh(maxnh) : Third Control vector of d.m. and overlap
34
33
C real*8 s(maxnh) : Overlap matrix in sparse form
35
C real*8 dm(maxnh,nspin) : Density matrix in sparse form
34
C real*8 dm(maxnh,spin%DM) : Density matrix in sparse form
36
35
C integer isa(natoms) : Species index of each atom
37
36
C integer lasto(0:maxa) : Index of last orbital of each atom
51
50
use atmfuncs, only : symfio, cnfigfio, labelfis, nofis
52
51
use alloc, only : re_alloc, de_alloc
53
use m_spin, only : spin
61
. iopt,natoms,nbasistot,maxnh,nspin
60
integer, intent(in) ::
61
. iopt,natoms,nbasistot,maxnh
64
64
. numh(*),lasto(0:natoms),listh(maxnh),listhptr(*),
65
65
. iphorb(*), isa(natoms), iaorb(*)
68
. dm(maxnh,nspin),s(maxnh)
68
. dm(maxnh,spin%DM),s(maxnh)
70
70
C Internal parameters ..................................................
71
71
C Number of columns in printout. Must be smaller than 20
84
84
. config(ncol), itot
87
. p(ncol),qa,qas(4),qts(4),qtot,qtot_temp,stot,svec(3)
87
. p(ncol),qa,qas(4),qts(4),qtot,qtot_temp,stot,svec(3)
89
90
real(dp), pointer :: qo(:)=>null(), qos(:,:)=>null()
279
280
. dictRef='siesta:mulliken',
280
281
. title='Mulliken Population Analysis')
283
if (nspin .eq. 2) then
284
if (spin%DM .eq. 2) then
284
285
if(is .eq. 1) then
285
286
if (ionode) write(6,'(/,a)') 'mulliken: Spin UP '
286
287
if (cml_p) call cmlStartPropertyList(xf=mainXML,
400
401
if (cml_p) call cmlEndPropertyList(xf=mainXML) ! mulliken
402
elseif (nspin .eq. 4) then
403
call re_alloc( qos, 1, nspin, 1, nbasistot,
403
elseif (spin%DM .ge. 4) then
404
call re_alloc( qos, 1, spin%Grid, 1, nbasistot,
404
405
& 'qos', 'mulliken' )
407
408
do io = 1,nbasistot
408
409
qos(is,io) = 0.0_dp
411
412
! For SOC-onsite, dm(:,4) has the wrong sign, but this
412
413
! routine is not called ('moments' is).
415
call LocalToGlobalOrb(io,Node, Nodes, itot)
415
call LocalToGlobalOrb(io,Node, Nodes, itot)
417
417
ind = listhptr(io)+in
419
qos(is,itot) = qos(is,itot) + dm(ind,is)*s(ind)/2
420
if ( jo <= nbasistot )
421
. qos(is,jo) = qos(is,jo) + dm(ind,is)*s(ind)/2
419
dm_aux(1:4) = dm(ind,1:4)
421
dm_aux(3) = 0.5_dp*(dm_aux(3)+dm(ind,7))
422
dm_aux(4) = 0.5_dp*(dm_aux(4)+dm(ind,8))
425
qos(is,itot) = qos(is,itot) + dm_aux(is)*s(ind)/2
426
if ( jo <= nbasistot )
427
. qos(is,jo) = qos(is,jo) + dm_aux(is)*s(ind)/2
426
call re_alloc( qb, 1, nspin*nbasistot,
432
call re_alloc( qb, 1, spin%Grid*nbasistot,
427
433
& 'qb', 'mulliken' )
428
call MPI_Reduce(qos(1,1), qb(1), nspin*nbasistot,
434
call MPI_Reduce(qos(1,1), qb(1), spin%Grid*nbasistot,
429
435
& Mpi_Double_Precision, MPI_Sum,
430
436
& 0, MPI_Comm_world, MPIerror)
432
438
do io = 1 , nbasistot
439
do is = 1 , spin%Grid
435
441
qos(is, io) = qb(itot)
462
468
if ( isa(ia) /= ispec ) cycle
464
470
! Initialize atomic charges (per spin)
471
qas(1:spin%Grid) = 0._dp
466
472
do io = lasto(ia-1)+1, lasto(ia)
468
474
C DSP, Writing symmetries for each orbital.
471
477
config(1) = cnfigfio(ispec,iphorb(io))
473
479
! Reduce total charge per-atom
480
do is = 1 , spin%Grid
475
481
qas(is) = qas(is) + qos(is,io)
478
call spnvec( nspin, qos(1:nspin,io),
484
call spnvec( spin%Grid, qos(1:spin%Grid,io),
479
485
$ qtot, stot, svec)
480
486
if ( IONode ) then
481
487
write(6,'(i5,i3,tr1,i1,a7,2f10.5,3x,3f8.3)')
486
492
end do ! atomic orbitals
488
call spnvec( nspin, qas, qtot, stot, svec )
494
call spnvec( spin%Grid, qas, qtot, stot, svec )
489
495
if ( IONode ) then
490
496
write(6,'(i5,5x,a5,2x,2f10.5,3x,3f8.3,/)')
491
497
. ia, 'Total', qtot, stot, svec
494
500
! Reduce total charge in system
501
do is = 1 , spin%Grid
496
502
qts(is) = qts(is) + qas(is)
499
505
end do ! loop atoms
501
call spnvec( nspin, qts, qtot, stot, svec )
507
call spnvec( spin%Grid, qts, qtot, stot, svec )
502
508
if ( IONode ) then
503
509
write(6,'(a,/,a5,12x,2f10.5,3x,3f8.3,/)')
504
510
. repeat('-',64), 'Total', qtot, stot, svec
521
527
11 format(i12,20(1x,f7.3))
522
528
15 format(i4,1x,i1,a7,20(1x,f8.3))
530
end subroutine mulliken