Commit 5ecad916 authored by Gregor Michalicek's avatar Gregor Michalicek

Move metric calls from the broyden2 to the mix subroutine

This implies the reduction of required metric calls in the broyden code path
from 4 to 2. This is now equivalent to the number of metric calls in the
old broyden code path.
parent 462d16e8
...@@ -13,13 +13,14 @@ IMPLICIT NONE ...@@ -13,13 +13,14 @@ IMPLICIT NONE
CONTAINS CONTAINS
SUBROUTINE readLastIterInAndDiffDen(hybrid,vecLen,nextIter,alpha,inDenVec,diffDenVec) SUBROUTINE readLastIterInAndDiffDen(hybrid,vecLen,nextIter,alpha,inDenVec,diffDenVec,inDenVecMet,diffDenVecMet)
TYPE(t_hybrid), INTENT(IN) :: hybrid TYPE(t_hybrid), INTENT(IN) :: hybrid
INTEGER, INTENT(IN) :: vecLen INTEGER, INTENT(IN) :: vecLen
INTEGER, INTENT(OUT) :: nextIter INTEGER, INTENT(OUT) :: nextIter
REAL, INTENT(OUT) :: alpha REAL, INTENT(OUT) :: alpha
REAL, INTENT(OUT) :: inDenVec(vecLen), diffDenVec(vecLen) REAL, INTENT(OUT) :: inDenVec(vecLen), diffDenVec(vecLen)
REAL,OPTIONAL, INTENT(OUT) :: inDenVecMet(vecLen), diffDenVecMet(vecLen)
INTEGER :: mode INTEGER :: mode
...@@ -33,18 +34,23 @@ SUBROUTINE readLastIterInAndDiffDen(hybrid,vecLen,nextIter,alpha,inDenVec,diffDe ...@@ -33,18 +34,23 @@ SUBROUTINE readLastIterInAndDiffDen(hybrid,vecLen,nextIter,alpha,inDenVec,diffDe
OPEN (57,file='broyd',form='unformatted',status='unknown') OPEN (57,file='broyd',form='unformatted',status='unknown')
ENDIF ENDIF
READ(57) nextIter,alpha,diffDenVec,inDenVec IF(PRESENT(inDenVecMet)) THEN
READ(57) nextIter,alpha,diffDenVec,inDenVec,inDenVecMet,diffDenVecMet
ELSE
READ(57) nextIter,alpha,diffDenVec,inDenVec
END IF
CLOSE(57) CLOSE(57)
END SUBROUTINE readLastIterInAndDiffDen END SUBROUTINE readLastIterInAndDiffDen
SUBROUTINE writeLastIterInAndDiffDen(hybrid,vecLen,nextIter,alpha,inDenVec,diffDenVec) SUBROUTINE writeLastIterInAndDiffDen(hybrid,vecLen,nextIter,alpha,inDenVec,diffDenVec,inDenVecMet,diffDenVecMet)
TYPE(t_hybrid), INTENT(IN) :: hybrid TYPE(t_hybrid), INTENT(IN) :: hybrid
INTEGER, INTENT(IN) :: nextIter,vecLen INTEGER, INTENT(IN) :: nextIter,vecLen
REAL, INTENT(IN) :: alpha REAL, INTENT(IN) :: alpha
REAL, INTENT(IN) :: inDenVec(vecLen), diffDenVec(vecLen) REAL, INTENT(IN) :: inDenVec(vecLen), diffDenVec(vecLen)
REAL,OPTIONAL, INTENT(IN) :: inDenVecMet(vecLen), diffDenVecMet(vecLen)
INTEGER :: mode INTEGER :: mode
...@@ -58,7 +64,11 @@ SUBROUTINE writeLastIterInAndDiffDen(hybrid,vecLen,nextIter,alpha,inDenVec,diffD ...@@ -58,7 +64,11 @@ SUBROUTINE writeLastIterInAndDiffDen(hybrid,vecLen,nextIter,alpha,inDenVec,diffD
OPEN (57,file='broyd',form='unformatted',status='unknown') OPEN (57,file='broyd',form='unformatted',status='unknown')
ENDIF ENDIF
WRITE(57) nextIter,alpha,diffDenVec,inDenVec IF(PRESENT(inDenVecMet)) THEN
WRITE(57) nextIter,alpha,diffDenVec,inDenVec,inDenVecMet,diffDenVecMet
ELSE
WRITE(57) nextIter,alpha,diffDenVec,inDenVec
END IF
CLOSE(57) CLOSE(57)
......
...@@ -56,11 +56,11 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,& ...@@ -56,11 +56,11 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,&
INTEGER i,imap,js INTEGER i,imap,js
INTEGER mmap,mmaph,nmaph,nmap,mapmt,mapvac,mapvac2 INTEGER mmap,mmaph,nmaph,nmap,mapmt,mapvac,mapvac2
INTEGER iofl,n_u_keep INTEGER iofl,n_u_keep
LOGICAL l_exist,l_ldaU, l_densityMatrixPresent LOGICAL l_exist,l_ldaU, l_densityMatrixPresent, l_pot
!Local Arrays !Local Arrays
REAL dist(6) REAL dist(6)
REAL, ALLOCATABLE :: sm(:), fsm(:) REAL, ALLOCATABLE :: sm(:), fsm(:), fmMet(:), smMet(:)
CHARACTER(LEN=20) :: attributes(2) CHARACTER(LEN=20) :: attributes(2)
COMPLEX :: n_mmpTemp(-3:3,-3:3,MAX(1,atoms%n_u),input%jspins) COMPLEX :: n_mmpTemp(-3:3,-3:3,MAX(1,atoms%n_u),input%jspins)
...@@ -116,6 +116,7 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,& ...@@ -116,6 +116,7 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,&
! LDA+U (end) ! LDA+U (end)
ALLOCATE (sm(mmap),fsm(mmap)) ALLOCATE (sm(mmap),fsm(mmap))
ALLOCATE (smMet(mmap),fmMet(mmap))
dist(:) = 0.0 dist(:) = 0.0
!determine type of mixing: !determine type of mixing:
...@@ -150,14 +151,26 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,& ...@@ -150,14 +151,26 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,&
!store the difference fsm - sm in fsm !store the difference fsm - sm in fsm
fsm(:nmap) = fsm(:nmap) - sm(:nmap) fsm(:nmap) = fsm(:nmap) - sm(:nmap)
l_pot = .FALSE.
! Apply metric w to fsm and store in fmMet: w |fsm>
CALL metric(cell,atoms,vacuum,sphhar,input,noco,stars,sym,oneD,&
mmap,nmaph,mapmt,mapvac2,fsm,fmMet,l_pot)
!mixing of the densities !mixing of the densities
IF (input%imix.EQ.0) THEN IF (input%imix.EQ.0) THEN
CALL stmix(atoms,input,noco, nmap,nmaph,fsm, sm) CALL stmix(atoms,input,noco, nmap,nmaph,fsm, sm)
ELSE ELSE
CALL broyden(cell,stars,atoms,vacuum,sphhar,input,noco,oneD,sym,& CALL broyden(cell,stars,atoms,vacuum,sphhar,input,noco,oneD,sym,&
hybrid,mmap,nmaph,mapmt,mapvac2,nmap,fsm,sm) hybrid,mmap,nmaph,mapmt,mapvac2,nmap,fsm,sm)
! Replace the broyden call above by the commented metric and broyden2 calls
! below to switch on the continuous restart of the Broyden method.
! ! Apply metric w to sm and store in smMet: w |sm>
! CALL metric(cell,atoms,vacuum,sphhar,input,noco,stars,sym,oneD,&
! mmap,nmaph,mapmt,mapvac2,sm,smMet,l_pot)
!
! CALL broyden2(cell,stars,atoms,vacuum,sphhar,input,noco,oneD,sym,& ! CALL broyden2(cell,stars,atoms,vacuum,sphhar,input,noco,oneD,sym,&
! hybrid,mmap,nmaph,mapmt,mapvac2,nmap,fsm,sm) ! hybrid,mmap,nmaph,mapmt,mapvac2,nmap,fsm,sm,fmMet,smMet)
END IF END IF
!initiatlize mixed density and extract it with brysh2 call !initiatlize mixed density and extract it with brysh2 call
...@@ -171,8 +184,8 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,& ...@@ -171,8 +184,8 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,&
!calculate the distance of charge densities... !calculate the distance of charge densities...
!induce metric in fsm use sm as an output array: |sm> = w |fsm> !induce metric in fsm use sm as an output array: |sm> = w |fsm>
CALL metric(cell,atoms,vacuum,sphhar,input,noco,stars,sym,oneD,& ! CALL metric(cell,atoms,vacuum,sphhar,input,noco,stars,sym,oneD,&
mmap,nmaph,mapmt,mapvac2,fsm, sm) ! mmap,nmaph,mapmt,mapvac2,fsm, sm)
!calculate the charge density distance for each spin !calculate the charge density distance for each spin
IF(hybrid%l_calhf) THEN IF(hybrid%l_calhf) THEN
...@@ -182,7 +195,7 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,& ...@@ -182,7 +195,7 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,&
END IF END IF
DO js = 1,input%jspins DO js = 1,input%jspins
dist(js) = CPP_BLAS_sdot(nmaph,fsm(nmaph*(js-1)+1),1, sm(nmaph*(js-1)+1),1) dist(js) = CPP_BLAS_sdot(nmaph,fsm(nmaph*(js-1)+1),1, fmMet(nmaph*(js-1)+1),1)
attributes = '' attributes = ''
WRITE(attributes(1),'(i0)') js WRITE(attributes(1),'(i0)') js
...@@ -196,14 +209,14 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,& ...@@ -196,14 +209,14 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,&
WRITE ( 6,FMT=7900) js,inDen%iter,1000*SQRT(ABS(dist(js)/cell%vol)) WRITE ( 6,FMT=7900) js,inDen%iter,1000*SQRT(ABS(dist(js)/cell%vol))
END IF END IF
END DO END DO
IF (noco%l_noco) dist(6) = CPP_BLAS_sdot((nmap-2*nmaph), fsm(nmaph*2+1),1,sm(nmaph*2+1),1) IF (noco%l_noco) dist(6) = CPP_BLAS_sdot((nmap-2*nmaph), fsm(nmaph*2+1),1,fmMet(nmaph*2+1),1)
IF (noco%l_noco) WRITE (6,FMT=7900) 3,inDen%iter,1000*SQRT(ABS(dist(6)/cell%vol)) IF (noco%l_noco) WRITE (6,FMT=7900) 3,inDen%iter,1000*SQRT(ABS(dist(6)/cell%vol))
!calculate the distance of total charge and spin density !calculate the distance of total charge and spin density
!|rho/m(o) - rho/m(i)| = |rh1(o) -rh1(i)|+ |rh2(o) -rh2(i)| +/_ !|rho/m(o) - rho/m(i)| = |rh1(o) -rh1(i)|+ |rh2(o) -rh2(i)| +/_
! +/_2<rh2(o) -rh2(i)|rh1(o) -rh1(i)> ! +/_2<rh2(o) -rh2(i)|rh1(o) -rh1(i)>
IF (input%jspins.EQ.2) THEN IF (input%jspins.EQ.2) THEN
dist(3) = CPP_BLAS_sdot(nmaph,fsm,1,sm(nmaph+1),1) dist(3) = CPP_BLAS_sdot(nmaph,fsm,1,fmMet(nmaph+1),1)
dist(4) = dist(1) + dist(2) + 2.0e0*dist(3) dist(4) = dist(1) + dist(2) + 2.0e0*dist(3)
dist(5) = dist(1) + dist(2) - 2.0e0*dist(3) dist(5) = dist(1) + dist(2) - 2.0e0*dist(3)
CALL writeXMLElementFormPoly('overallChargeDensity',(/'distance'/),& CALL writeXMLElementFormPoly('overallChargeDensity',(/'distance'/),&
...@@ -227,7 +240,7 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,& ...@@ -227,7 +240,7 @@ SUBROUTINE mix(stars,atoms,sphhar,vacuum,input,sym,cell,noco,oneD,&
!(e.g. when calculating non-magnetic systems with jspins=2). !(e.g. when calculating non-magnetic systems with jspins=2).
END IF END IF
results%last_distance=maxval(1000*SQRT(ABS(dist/cell%vol))) results%last_distance=maxval(1000*SQRT(ABS(dist/cell%vol)))
DEALLOCATE (sm,fsm) DEALLOCATE (sm,fsm,smMet,fmMet)
CALL closeXMLElement('densityConvergence') CALL closeXMLElement('densityConvergence')
!fix charge of the new density !fix charge of the new density
......
...@@ -29,7 +29,7 @@ MODULE m_broyden2 ...@@ -29,7 +29,7 @@ MODULE m_broyden2
!################################################################ !################################################################
CONTAINS CONTAINS
SUBROUTINE broyden2(cell,stars,atoms,vacuum,sphhar,input,noco,oneD,sym,& SUBROUTINE broyden2(cell,stars,atoms,vacuum,sphhar,input,noco,oneD,sym,&
hybrid,mmap,nmaph,mapmt,mapvac2,nmap,fm,sm,lpot) hybrid,mmap,nmaph,mapmt,mapvac2,nmap,fm,sm,fmMet,smMet,lpot)
#include"cpp_double.h" #include"cpp_double.h"
...@@ -58,6 +58,8 @@ CONTAINS ...@@ -58,6 +58,8 @@ CONTAINS
! Array Arguments ! Array Arguments
REAL, INTENT (IN) :: fm(nmap) REAL, INTENT (IN) :: fm(nmap)
REAL, INTENT (INOUT) :: sm(nmap) REAL, INTENT (INOUT) :: sm(nmap)
REAL, INTENT (IN) :: fmMet(nmap)
REAL, INTENT (INOUT) :: smMet(nmap)
! Local Scalars ! Local Scalars
INTEGER :: i,j,it,k,nit,iread,nmaph, mit, historyLength INTEGER :: i,j,it,k,nit,iread,nmaph, mit, historyLength
...@@ -65,7 +67,8 @@ CONTAINS ...@@ -65,7 +67,8 @@ CONTAINS
LOGICAL :: l_pot, l_exist LOGICAL :: l_pot, l_exist
! Local Arrays ! Local Arrays
REAL, ALLOCATABLE :: fm1(:),sm1(:),uVec(:),vVec(:) REAL, ALLOCATABLE :: fmLast(:),smLast(:),fmLastMet(:),smLastMet(:)
REAL, ALLOCATABLE :: uVec(:),vVec(:)
REAL, ALLOCATABLE :: dNVec(:),dFVec(:),dNMet(:), dFMet(:), FMet(:) REAL, ALLOCATABLE :: dNVec(:),dFVec(:),dNMet(:), dFMet(:), FMet(:)
REAL, ALLOCATABLE :: deltaN_i(:), deltaF_i(:) REAL, ALLOCATABLE :: deltaN_i(:), deltaF_i(:)
REAL, ALLOCATABLE :: dNdNMat(:,:), dNdFMat(:,:), dFdNMat(:,:), dFdFMat(:,:) REAL, ALLOCATABLE :: dNdNMat(:,:), dNdFMat(:,:), dFdNMat(:,:), dFdFMat(:,:)
...@@ -83,15 +86,16 @@ CONTAINS ...@@ -83,15 +86,16 @@ CONTAINS
l_pot = .FALSE. l_pot = .FALSE.
IF (PRESENT(lpot)) l_pot = lpot IF (PRESENT(lpot)) l_pot = lpot
ALLOCATE (fm1(mmap),sm1(mmap),dNVec(mmap),dFVec(mmap),uVec(mmap),vVec(mmap)) ALLOCATE (fmLast(mmap),smLast(mmap),fmLastMet(mmap),smLastMet(mmap))
ALLOCATE (dNVec(mmap),dFVec(mmap),uVec(mmap),vVec(mmap))
ALLOCATE (deltaN_i(mmap),deltaF_i(mmap)) ALLOCATE (deltaN_i(mmap),deltaF_i(mmap))
ALLOCATE (dNdNLast(input%maxiter),dFdFLast(input%maxiter)) ALLOCATE (dNdNLast(input%maxiter),dFdFLast(input%maxiter))
ALLOCATE (dNdFLast(input%maxiter),dFdNLast(input%maxiter)) ALLOCATE (dNdFLast(input%maxiter),dFdNLast(input%maxiter))
ALLOCATE (dnMet(mmap), dFMet(mmap), FMet(mmap)) ALLOCATE (dNMet(mmap), dFMet(mmap), FMet(mmap))
fm1 = 0.0 fmLast = 0.0
sm1 = 0.0 smLast = 0.0
dNVec = 0.0 dNVec = 0.0
dFVec = 0.0 dFVec = 0.0
vVec = 0.0 vVec = 0.0
...@@ -103,26 +107,29 @@ CONTAINS ...@@ -103,26 +107,29 @@ CONTAINS
IF(.NOT.l_exist) mit = 1 IF(.NOT.l_exist) mit = 1
IF (mit.NE.1) THEN IF (mit.NE.1) THEN
! load input charge density (sm1) and difference of ! load input charge density (smLast) and difference of
! in and out charge densities (fm1) from previous iteration (m-1) ! in and out charge densities (fmLast) from previous iteration (m-1)
CALL readLastIterInAndDiffDen(hybrid,nmap,mit,alphan,sm1(:nmap),fm1(:nmap)) CALL readLastIterInAndDiffDen(hybrid,nmap,mit,alphan,smLast(:nmap),fmLast(:nmap),smLastMet(:nmap),fmLastMet(:nmap))
IF (ABS(input%alpha-alphan) > 0.0001) THEN IF (ABS(input%alpha-alphan) > 0.0001) THEN
WRITE (6,*) 'mixing parameter has been changed; reset' WRITE (6,*) 'mixing parameter has been changed; reset'
WRITE (6,*) 'broyden algorithm or set alpha to',alphan WRITE (6,*) 'broyden algorithm or set alpha to',alphan
CALL juDFT_error("mixing parameter (input) changed", calledby ="broyden") CALL juDFT_error("mixing parameter (input) changed", calledby ="broyden")
END IF END IF
! generate F_m - F_(m-1) ... sm1 ! generate F_m - F_(m-1) ... smLast
! and rho_m - rho_(m-1) .. fm1 ! and rho_m - rho_(m-1) .. fmLast
dNVec(1:nmap) = sm(1:nmap) - sm1(1:nmap) dNVec(1:nmap) = sm(1:nmap) - smLast(1:nmap)
dFVec(1:nmap) = fm(1:nmap) - fm1(1:nmap) dFVec(1:nmap) = fm(1:nmap) - fmLast(1:nmap)
dNMet(1:nmap) = smMet(1:nmap) - smLastMet(1:nmap)
dFMet(1:nmap) = fmMet(1:nmap) - fmLastMet(1:nmap)
END IF END IF
! save F_m and rho_m for next iteration ! save F_m and rho_m for next iteration
nit = mit +1 nit = mit +1
IF (nit > input%maxiter+1) nit = 1 IF (nit > input%maxiter+1) nit = 1
CALL writeLastIterInAndDiffDen(hybrid,nmap,nit,input%alpha,sm,fm) CALL writeLastIterInAndDiffDen(hybrid,nmap,nit,input%alpha,sm,fm,smMet,fmMet)
IF (mit.EQ.1) THEN IF (mit.EQ.1) THEN
! update for rho for mit=1 is straight mixing ! update for rho for mit=1 is straight mixing
...@@ -134,12 +141,12 @@ CONTAINS ...@@ -134,12 +141,12 @@ CONTAINS
CALL writeDeltaFVec(input,hybrid,nmap,mit,dFVec) CALL writeDeltaFVec(input,hybrid,nmap,mit,dFVec)
! Apply metric w to dNVec and store in dNMet: w |dNVec> ! Apply metric w to dNVec and store in dNMet: w |dNVec>
CALL metric(cell,atoms,vacuum,sphhar,input,noco,stars,sym,oneD,& ! CALL metric(cell,atoms,vacuum,sphhar,input,noco,stars,sym,oneD,&
mmap,nmaph,mapmt,mapvac2,dNVec,dNMet,l_pot) ! mmap,nmaph,mapmt,mapvac2,dNVec,dNMet,l_pot)
! Apply metric w to dFVec and store in dFMet: w |dFVec> ! Apply metric w to dFVec and store in dFMet: w |dFVec>
CALL metric(cell,atoms,vacuum,sphhar,input,noco,stars,sym,oneD,& ! CALL metric(cell,atoms,vacuum,sphhar,input,noco,stars,sym,oneD,&
mmap,nmaph,mapmt,mapvac2,dFVec,dFMet,l_pot) ! mmap,nmaph,mapmt,mapvac2,dFVec,dFMet,l_pot)
! Extend overlap matrices <delta n(i) | delta n(j)>, <delta F(i) | delta F(j)>, ! Extend overlap matrices <delta n(i) | delta n(j)>, <delta F(i) | delta F(j)>,
! <delta n(i) | delta F(j)>, <delta F(i) | delta n(j)> -start- ! <delta n(i) | delta F(j)>, <delta F(i) | delta n(j)> -start-
...@@ -339,17 +346,17 @@ CONTAINS ...@@ -339,17 +346,17 @@ CONTAINS
! Construct the final uVec and vVec -end- ! Construct the final uVec and vVec -end-
! Apply metric w to dFVec and store in FMet: w |dFVec> ! Apply metric w to dFVec and store in FMet: w |dFVec>
CALL metric(cell,atoms,vacuum,sphhar,input,noco,stars,sym,oneD,& ! CALL metric(cell,atoms,vacuum,sphhar,input,noco,stars,sym,oneD,&
mmap,nmaph,mapmt,mapvac2,fm,FMet,l_pot) ! mmap,nmaph,mapmt,mapvac2,fm,FMet,l_pot)
vFMetProd = CPP_BLAS_sdot(nmap,vVec,1,FMet,1) vFMetProd = CPP_BLAS_sdot(nmap,vVec,1,fmMet,1)
! update rho(m+1) ! update rho(m+1)
! calculate sm(:) = (1.0-vFMetProd)*uVec(:) + sm ! calculate sm(:) = (1.0-vFMetProd)*uVec(:) + sm
CALL CPP_BLAS_saxpy(nmap,1.0-vFMetProd,uVec,1,sm,1) CALL CPP_BLAS_saxpy(nmap,1.0-vFMetProd,uVec,1,sm,1)
END IF END IF
DEALLOCATE (fm1,sm1,dNVec,dFVec,vVec) DEALLOCATE (fmLast,smLast,fmLastMet,smLastMet,dNVec,dFVec,vVec)
END SUBROUTINE broyden2 END SUBROUTINE broyden2
END MODULE m_broyden2 END MODULE m_broyden2
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment