Line data Source code
1 : MODULE m_broyden 2 : USE m_juDFT 3 : !################################################################ 4 : ! IMIX = 3 : BROYDEN'S FIRST METHOD 5 : ! IMIX = 5 : BROYDEN'S SECOND METHOD 6 : ! IMIX = 7 : GENERALIZED ANDERSEN METHOD 7 : ! sm : input charge density of iteration m 8 : ! afterwards update rho(m+1) 9 : ! fm : output minus input charge density of iteration m 10 : ! sm1 : input charge density of iteration m-1 11 : ! fm1 : output minus inputcharge density of iteration m-1 12 : !################################################################ 13 : CONTAINS 14 664 : SUBROUTINE broyden(alpha,fm,sm,l_dfpt) 15 : USE m_types 16 : USE m_types_mixvector 17 : IMPLICIT NONE 18 : 19 : real,INTENT(IN) :: alpha 20 : TYPE(t_mixvector),INTENT(IN) :: fm(:) 21 : TYPE(t_mixvector),INTENT(INOUT) :: sm(:) 22 : LOGICAL, INTENT(IN) :: l_dfpt 23 : 24 : ! Locals 25 : INTEGER :: n,it,hlen 26 : REAL :: fmvm,vmnorm 27 664 : REAL,ALLOCATABLE :: am(:),dfivi(:) 28 664 : TYPE(t_mixvector) :: fm1,sm1,ui,um,vi,vm 29 664 : TYPE(t_mixvector),allocatable :: u_store(:),v_store(:) 30 : 31 664 : hlen=size(fm) 32 664 : IF (hlen<2) THEN !Do a simple mixing step 33 144 : sm(hlen)=sm(hlen)+alpha*fm(hlen) 34 144 : RETURN 35 : ENDIF 36 : 37 8668 : ALLOCATE(u_store(hlen-2),v_store(hlen-2)) 38 3814 : do it=1,hlen-2 39 3294 : call u_store(it)%alloc() 40 3814 : call v_store(it)%alloc() 41 : enddo 42 : 43 520 : CALL fm1%alloc() 44 520 : CALL sm1%alloc() 45 520 : CALL ui%alloc() 46 520 : CALL um%alloc() 47 520 : CALL vi%alloc() 48 520 : CALL vm%alloc() 49 : 50 2080 : ALLOCATE (am(hlen-1),dfivi(hlen-1)) 51 4334 : dfivi = 0.0 52 4334 : am = 0.0 53 520 : call timestart("Broyden-loop") 54 4334 : DO n=2,hlen 55 3814 : sm1 = sm(n) - sm(n-1) 56 3814 : fm1 = fm(n) - fm(n-1) 57 : ! |vi> = w|vi> 58 : ! loop to generate um : um = sm1 + alpha*fm1 - \sum <fm1|w|vi> ui 59 3814 : um = alpha * fm1 + sm1 60 3814 : call timestart("Broyden-1.loop") 61 23438 : DO it = n-2,1,-1 62 19624 : ui=u_store(it) 63 19624 : vi=v_store(it) 64 : 65 19624 : am(it) = vi.dot.fm1 66 : ! calculate um(:) = -am(it)*ui(:) + um(:) 67 23438 : um=um-am(it)*ui 68 : !WRITE(oUnit,FMT='(5x,"<vi|w|Fm> for it",i2,5x,f10.6)')it,am(it) 69 : END DO 70 3814 : call timestop("Broyden-1.loop") 71 : 72 : ! calculate vm = alpha*wfm1 -\sum <fm1|w|vi> <fi1|w|vi><vi| 73 : ! convolute fm1 with the metrik and store in vm 74 3814 : vm=fm1%apply_metric(l_dfpt) 75 3814 : call timestart("Broyden-2.loop") 76 23438 : DO it = n-2,1,-1 77 19624 : vi=v_store(it) 78 : ! calculate vm(:) = -am(it)*dfivi*vi(:) + vm 79 23438 : vm=vm-am(it)*dfivi(it)*vi 80 : END DO 81 3814 : call timestop("Broyden-2.loop") 82 : 83 3814 : vmnorm=fm1.dot.vm 84 : ! if (vmnorm.lt.tol_10) stop 85 : 86 : ! calculate vm(:) = (1.0/vmnorm)*vm(:) 87 3814 : vm=(1.0/vmnorm)*vm 88 : 89 : ! save dfivi(mit) for next iteration 90 3814 : dfivi(n-1) = vmnorm 91 3814 : IF (n<hlen) u_store(n-1)=um 92 4334 : IF (n<hlen) v_store(n-1)=vm 93 : enddo 94 520 : call timestop("Broyden-loop") 95 : ! update rho(m+1) 96 : ! calculate <fm|w|vm> 97 520 : fmvm = vm.dot.fm(hlen) 98 : ! calculate sm(:) = (1.0-fmvm)*um(:) + sm 99 520 : sm(hlen)=sm(hlen)+(1.0-fmvm)*um 100 : 101 7252 : END SUBROUTINE broyden 102 : END MODULE m_broyden