broyden_history.F90 2.75 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
MODULE m_broyden
  USE m_juDFT
  !################################################################
  !     IMIX = 3 : BROYDEN'S FIRST METHOD
  !     IMIX = 5 : BROYDEN'S SECOND METHOD
  !     IMIX = 7 : GENERALIZED ANDERSEN METHOD
  !     sm   : input charge density of iteration m
  !            afterwards update rho(m+1)
  !     fm   : output minus input charge density of iteration m
  !     sm1  : input charge density of iteration m-1
  !     fm1   : output minus inputcharge density of iteration m-1
  !################################################################
CONTAINS
  SUBROUTINE broyden(alpha,fm,sm)
    USE m_types
    USE m_types_mixvector
    IMPLICIT NONE

    real,INTENT(IN)                 :: alpha
    TYPE(t_mixvector),INTENT(IN)    :: fm(:)
    TYPE(t_mixvector),INTENT(INOUT) :: sm(:)

    ! Locals
    INTEGER           :: n,it,hlen
Daniel Wortmann's avatar
Daniel Wortmann committed
25 26
    REAL              :: fmvm,vmnorm
    REAL,ALLOCATABLE  :: am(:),dfivi(:)
27
    TYPE(t_mixvector) :: fm1,sm1,ui,um,vi,vm
Daniel Wortmann's avatar
Daniel Wortmann committed
28
    TYPE(t_mixvector),allocatable :: u_store(:),v_store(:)
29 30

    hlen=size(fm)
31 32 33 34 35
    IF (hlen<2) THEN !Do a simple mixing step
       sm(hlen)=sm(hlen)+alpha*fm(hlen)
       RETURN
    ENDIF

Daniel Wortmann's avatar
Daniel Wortmann committed
36 37
    ALLOCATE(u_store(hlen-2),v_store(hlen-2))
    do it=1,hlen-2
38 39 40 41 42 43 44 45 46 47 48
       call u_store(it)%alloc()
       call v_store(it)%alloc()
    enddo
     
    CALL fm1%alloc()
    CALL sm1%alloc()
    CALL ui%alloc()
    CALL um%alloc()
    CALL vi%alloc()
    CALL vm%alloc()
    
Daniel Wortmann's avatar
Daniel Wortmann committed
49 50
    ALLOCATE (am(hlen-1),dfivi(hlen-1))
    dfivi = 0.0
51 52 53 54 55 56 57 58 59
    am  = 0.0
    DO n=2,hlen
       sm1 = sm(n) - sm(n-1)
       fm1 = fm(n) - fm(n-1)
       !     |vi> = w|vi> 
       !     loop to generate um : um = sm1 + alpha*fm1 - \sum <fm1|w|vi> ui
       um = alpha * fm1 + sm1
       
       DO it = n-2,1,-1
Daniel Wortmann's avatar
Daniel Wortmann committed
60 61
          ui=u_store(it)
          vi=v_store(it)
62
          
Daniel Wortmann's avatar
Daniel Wortmann committed
63
          am(it) = vi.dot.fm1
64 65 66 67 68 69 70 71 72
          ! calculate um(:) = -am(it)*ui(:) + um(:)
          um=um-am(it)*ui
          WRITE(6,FMT='(5x,"<vi|w|Fm> for it",i2,5x,f10.6)')it,am(it) 
       END DO

       ! calculate vm = alpha*wfm1 -\sum <fm1|w|vi> <fi1|w|vi><vi|
       ! convolute fm1 with the metrik and store in vm
       vm=fm1%apply_metric()
       DO it = n-2,1,-1
Daniel Wortmann's avatar
Daniel Wortmann committed
73
          vi=v_store(it)
74
          ! calculate vm(:) = -am(it)*dfivi*vi(:) + vm
Daniel Wortmann's avatar
Daniel Wortmann committed
75
          vm=vm-am(it)*dfivi(it)*vi
76 77 78 79 80 81 82 83 84
       END DO

       vmnorm=fm1.dot.vm
       ! if (vmnorm.lt.tol_10) stop

       ! calculate vm(:) = (1.0/vmnorm)*vm(:)
       vm=(1.0/vmnorm)*vm
     
       ! save dfivi(mit) for next iteration
Daniel Wortmann's avatar
Daniel Wortmann committed
85 86 87
       dfivi(n-1) = vmnorm
       IF (n<hlen) u_store(n-1)=um
       IF (n<hlen) v_store(n-1)=vm
88 89 90
    enddo
    ! update rho(m+1)
    ! calculate <fm|w|vm>
Daniel Wortmann's avatar
Daniel Wortmann committed
91
    fmvm = vm.dot.fm(hlen)
92
    ! calculate sm(:) = (1.0-fmvm)*um(:) + sm
Daniel Wortmann's avatar
Daniel Wortmann committed
93
    sm(hlen)=sm(hlen)+(1.0-fmvm)*um
94 95 96
 
  END SUBROUTINE broyden
END MODULE m_broyden