restart.f90

来自「用于计算矩阵的特征值,及矩阵的其他运算.可以用与稀疏矩阵」· F90 代码 · 共 879 行 · 第 1/2 页

F90
879
字号
              kr = kr - 1              kl = kl - 1           Else              i = 0           End If        Else           i = 0        End If     End Do  End IfEnd Subroutine trl_restart_scan!!!! save those that are close to converge (as close as the target)!!!Subroutine trl_restart_small_res(nd, mnd, tind, lambda, res, info, kl, kr)  Use trl_info  Implicit None  Type(TRL_INFO_T), Intent(in) :: info  Integer, Intent(in) :: nd, mnd, tind  Integer, Intent(inout) :: kl, kr  Real(8), Intent(in) :: lambda(nd), res(nd)  Interface     Function trl_min_gap_ratio(info, nd, tind, res) Result(gamma)       Use trl_info       Implicit None       Type(TRL_INFO_T), Intent(in) :: info       Integer, Intent(in) :: nd, tind       Real(8), Intent(in) :: res(nd)       Real(8) :: gamma     End Function trl_min_gap_ratio  End Interface  !  ! local variables  Integer :: extra, i, j, ii, kl0, kr0, minsep  Real(8) :: acpt, resmax, gmin  ! the number of extra Ritz pairs to be saved  minsep = Max(3, nd/5, nd-4*info%ned)  extra = Nint((mnd-info%nec)*(0.4D0+0.1D0*info%ned/Dble(mnd)))  If (extra.Gt.info%ned+info%ned .And. extra.Gt.5) Then     gmin = Dble(mnd)/Dble(info%ned)     extra = Nint((extra + (Log(gmin)*info%ned) * gmin) / (1.0D0 +&          & gmin))  End If  kl0 = kl  kr0 = kr  resmax = Maxval(res)  acpt = resmax / res(tind)  !  ! determine the number of Ritz pairs that has to be saved  If (info%lohi .Gt. 0) Then     If (acpt.Lt.0.999D0 .And. acpt.Ge.0.0D0) Then        ii = tind - 1        acpt = Max(Sqrt(acpt)*res(tind), res(ii)+res(ii))        acpt = Min(acpt, resmax)        kr = ii - 1        Do While (res(kr).Lt.acpt .And. kr.Gt.kl+3)           kr = kr - 1        End Do     Else        kr = kr0 - extra     End If     kr = Max(3, kr)     kl = Min(kl, kr-2)  Else If (info%lohi .Lt. 0) Then     If (acpt.Lt.0.999D0 .And. acpt.Ge.0.0D0) Then        ii = tind + 1        acpt = Max(Sqrt(acpt)*res(tind), res(ii)+res(ii))        acpt = Min(acpt, resmax)        kl = ii + 1        Do While (res(kl).Lt.acpt .And. kl.Lt.kr-3)           kl = kl + 1        End Do     Else        kl = kl0 + extra     End If     kl = Min(nd-3, kl)     kr = Max(kr, kl+2)  Else     ! save whoever has smaller residual norms     i = kl + 1     j = kr - 1     Do ii = 1, extra        If (res(i) .Lt. res(j)) Then           kl = i           i = i + 1        Else If (res(i) .Gt. res(j)) Then           kr = j           j = j - 1        Else If (i .Le. nd-j) Then           kl = i           i = i + 1        Else           kr = j           j = j - 1        End If     End Do  End If  ! adjust kl and kr until the minimal gap ratio is satisfied  kl0 = kl  kr0 = kr  gmin = trl_min_gap_ratio(info, nd, tind, res)  Do While (kl+minsep.Lt.kr .And. gap_ratio(Max(1,kl),Min(nd,kr)).Lt.gmin)     If (info%lohi .Lt. 0) Then        kl = kl + 1     Else If (info%lohi .Gt. 0) Then        kr = kr - 1     Else If (res(kl) .Lt. res(kr)) Then        kl = kl + 1     Else        kr = kr + 1     End If  End Do  ! make sure nearly degenerate Ritz pairs are included  ! lambda(kl)+r(kl) > lambda(j) and   !                lambda(kl)-r(kl) > lambda(j)-r(j)  If (info%lohi .Gt. 0) Then     i = kr0-1     Do While (i.Gt.kl+minsep .And. lambda(kr)-res(kr).Lt.lambda(i) .And.&          & lambda(kr)+res(kr).Lt.lambda(i)+res(i))        i = i - 1     End Do     kr = Min(kr, i+1)  Else     i = kl0 + 1     Do While (i.Lt.kr-minsep .And. lambda(kl)+res(kl).Gt.lambda(i) .And.&          & lambda(kl)-res(kl).Gt.lambda(i)-res(i))        i = i + 1     End Do     kl = Max(kl, i-1)  End IfContains  Function gap_ratio(i,j) Result(gamma)    Integer, Intent(in) :: i, j    Real(8) :: gamma    gamma = (lambda(i) - lambda(tind)) / (lambda(j) - lambda(tind))    Return  End Function gap_ratioEnd Subroutine trl_restart_small_res!!!! search throught all pairs of (kl, kr) for the one with the maximum! gap ratio for the next Ritz pair(target)!! This is an optimized version of the original version.  It only search! through nd number once. (Only single loop!)!!!Subroutine trl_restart_max_gap_ratio(nd, tind, kept, lambda, res, info, kl, kr)  Use trl_info  Implicit None  Type(TRL_INFO_T), Intent(in) :: info  Integer, Intent(in) :: kept, nd, tind  Integer, Intent(inout) :: kl, kr  Real(8), Intent(in) :: lambda(nd), res(nd)  Interface     Subroutine trl_restart_search_range(nd, lambda, res, info, ncl,&          & ncr, lohi, tind, klm, krm)       Use trl_info       Implicit None       Type(TRL_INFO_T), Intent(in) :: info       Integer, Intent(in) :: nd, ncl, ncr, tind       Integer, Intent(out) :: klm, krm, lohi       Real(8), Intent(in) :: lambda(nd), res(nd)     End Subroutine trl_restart_search_range     Function trl_min_gap_ratio(info, nd, tind, res) Result(gamma)       Use trl_info       Implicit None       Type(TRL_INFO_T), Intent(in) :: info       Integer, Intent(in) :: nd, tind       Real(8), Intent(in) :: res(nd)       Real(8) :: gamma     End Function trl_min_gap_ratio  End Interface  !  ! local variables  Integer :: i, j, lohi, klm, krm, igap  Real(8) :: bnd, tmp, gratio  ! statement function for computing gap ratio  gratio(i,j) = (lambda(i)-info%trgt)/(lambda(j)-info%trgt)  ! determine the search range  Call trl_restart_search_range(nd, lambda, res, info, kl, kr, lohi,&       & tind, klm, krm)  kl = klm  kr = krm  igap = Max(Min(nd-info%ned, Nint((krm-klm)*0.4D0)), 2)  If (igap.Gt.2 .And. info%matvec.Gt.info%maxlan) Then     If (info%clk_op+info%tick_o.Gt.1.0D1*(info%clk_orth&          &+info%tick_h+info%clk_res+info%tick_r)) Then        igap = Max(2, nd-kept-1)     Else        bnd = trl_min_gap_ratio(info, nd, tind, res)        If (info%crat .Lt. bnd) igap = Max(2, nd-kept-1)     End If  End If  If (kl+igap .Gt. kr) Return  ! two cases depending on lohi  If (lohi .Gt. 0) Then     ! target is at the high end of spectrum     bnd = gratio(kr, kl)     Do i = klm, krm-igap        j = i + igap        tmp = gratio(j,i)        If (tmp .Gt. bnd) Then           kl = i           kr = j           bnd = tmp        End If     End Do  Else     bnd = gratio(kl, kr)     Do i = klm, krm-igap        j = i + igap        tmp = gratio(i,j)        If (tmp .Gt. bnd) Then           kl = i           kr = j           bnd = tmp        End If     End Do  End IfEnd Subroutine trl_restart_max_gap_ratio!!!! search for a pair (kl, kr) such that the reduction in residual norm! of the target (info%trgt) will be the largest before next restart! The merit function is [gap-ratio * (m-k)]!!!Subroutine trl_restart_max_progress(nd, tind, kept, lambda, res, info, kl, kr)  Use trl_info  Implicit None  Type(TRL_INFO_T), Intent(in) :: info  Integer, Intent(in) :: kept, nd, tind  Integer, Intent(inout) :: kl, kr  Real(8), Intent(in) :: lambda(nd), res(nd)  Interface     Subroutine trl_restart_search_range(nd, lambda, res, info, ncl,&          & ncr, lohi, tind, klm, krm)       Use trl_info       Implicit None       Type(TRL_INFO_T), Intent(in) :: info       Integer, Intent(in) :: nd, ncl, ncr, tind       Integer, Intent(out) :: klm, krm, lohi       Real(8), Intent(in) :: lambda(nd), res(nd)     End Subroutine trl_restart_search_range     Function trl_min_gap_ratio(info, nd, tind, res) Result(gamma)       Use trl_info       Implicit None       Type(TRL_INFO_T), Intent(in) :: info       Integer, Intent(in) :: nd, tind       Real(8), Intent(in) :: res(nd)       Real(8) :: gamma     End Function trl_min_gap_ratio  End Interface  !  ! local variables  Integer :: i, j, lohi, klm, krm, igap  Real(8) :: tmp, ss, merit  ! merit measure the factor of residual norm reduction  merit(i,j) = (lambda(i)-info%trgt) * Abs(j-i) / (lambda(j)-info%trgt)  ! determine the search range  Call trl_restart_search_range(nd, lambda, res, info, kl, kr, lohi,&       & tind, klm, krm)  ! perform the brute-force search  kl = klm  kr = krm  igap = Max(Min(nd-info%ned, Nint((krm-klm)*0.4D0)), 2)  If (igap.Gt.2 .And. igap+kept.Gt.nd .And. info%crat.Gt.0.0D0) Then     ss = trl_min_gap_ratio(info, nd, tind, res)     If (ss .Gt. info%crat) igap = Max(2, nd-kept-1)  End If  If (lohi .Gt. 0) Then     ss = merit(kr, kl)     Do i = klm, krm-igap        Do j = i+igap, krm           tmp = merit(j, i)           If (tmp.Gt.ss) Then              ss = tmp              kl = i              kr = j           End If        End Do     End Do  Else     ss = merit(kl, kr)     Do i = klm, krm-igap        Do j = i+igap, krm           tmp = merit(i,j)           If (tmp.Gt.ss) Then              ss = tmp              kl = i              kr = j           End If        End Do     End Do  End IfEnd Subroutine trl_restart_max_progress!!!! search for a pair (kl, kr) such that the reduction in residual norm! of the target (info%trgt) will be the largest before next restart! the merit function is [sqrt(gap ratio) * (m-k)]!!!Subroutine trl_restart_max_reduction(nd, tind, kept, lambda, res, info, kl, kr)  Use trl_info  Implicit None  Type(TRL_INFO_T), Intent(in) :: info  Integer, Intent(in) :: kept, nd, tind  Integer, Intent(inout) :: kl, kr  Real(8), Intent(in) :: lambda(nd), res(nd)  Interface     Subroutine trl_restart_search_range(nd, lambda, res, info, ncl,&          & ncr, lohi, tind, klm, krm)       Use trl_info       Implicit None       Type(TRL_INFO_T), Intent(in) :: info       Integer, Intent(in) :: nd, ncl, ncr, tind       Integer, Intent(out) :: klm, krm, lohi       Real(8), Intent(in) :: lambda(nd), res(nd)     End Subroutine trl_restart_search_range     Function trl_min_gap_ratio(info, nd, tind, res) Result(gamma)       Use trl_info       Implicit None       Type(TRL_INFO_T), Intent(in) :: info       Integer, Intent(in) :: nd, tind       Real(8), Intent(in) :: res(nd)       Real(8) :: gamma     End Function trl_min_gap_ratio  End Interface  !  ! local variables  Integer :: i, j, lohi, klm, krm, igap  Real(8) :: tmp, ss, merit  ! merit measure the factor of residual norm reduction  merit(i,j) = Sqrt((lambda(i)-info%trgt)/(lambda(j)-info%trgt)) * Abs(j-i)  ! determine the search range  Call trl_restart_search_range(nd, lambda, res, info, kl, kr, lohi,&       & tind, klm, krm)  ! perform the brute-force search  kl = klm  kr = krm  igap = Max(Min(nd-info%ned, Nint((krm-klm)*0.4D0)), 2)  If (igap.Gt.2 .And. igap+kept.Gt.nd .And. info%crat.Gt.0.0D0) Then     ss = trl_min_gap_ratio(info, nd, tind, res)     If (ss .Gt. info%crat) igap = Max(2, nd-kept-1)  End If  If (lohi .Gt. 0) Then     ss = merit(kr, kl)     Do i = klm, krm-igap        Do j = i+igap, krm           tmp = merit(j, i)           If (tmp.Gt.ss) Then              ss = tmp              kl = i              kr = j           End If        End Do     End Do  Else     ss = merit(kl, kr)     Do i = klm, krm-igap        Do j = i+igap, krm           tmp = merit(i,j)           If (tmp.Gt.ss) Then              ss = tmp              kl = i              kr = j           End If        End Do     End Do  End IfEnd Subroutine trl_restart_max_reduction!!!! determine the search range -- used by the schemes that performs brute! -force search!!!Subroutine trl_restart_search_range(nd, lambda, res, info, ncl, ncr,&     & lohi, tind, klm, krm)  Use trl_info  Implicit None  Type(TRL_INFO_T), Intent(in) :: info  Integer, Intent(in) :: nd, ncl, ncr, tind  Integer, Intent(out) :: klm, krm, lohi  Real(8), Intent(in) :: lambda(nd), res(nd)  !  ! local variables  Integer :: j  Real(8) :: bnd  klm = Max(ncl,1)  krm = Min(ncr,nd)  bnd = info%tol * info%anrm  lohi = info%lohi  ! make sure there is some distance between the boundary and the  ! target Ritz value  If (info%lohi .Gt. 0) Then     ! save high end     krm = Min(Max(info%maxlan-info%ned, (info%maxlan+info%nec)/2),&          & krm, tind-1)     Do While (krm+krm.Ge.ncl+ncr .And. res(krm).Le.bnd)        krm = krm - 1     End Do  Else If (info%lohi .Lt. 0) Then     ! save lower end     klm = Max(Min(info%ned, (info%maxlan+info%nec)/2), tind+1, klm)     Do While (klm+klm.Le.ncl+ncr .And. res(klm).Le.bnd)        klm = klm + 1     End Do  Else     ! save both ends     If (tind-klm .Lt. krm-tind) Then        lohi = -1        klm = tind + 1     Else        lohi = 1        krm = tind - 1     End If     j = info%locked + klm + nd - krm + 1     If (j .Gt. 0) Then        j = j / 2        klm = klm - j        krm = krm + j     End If  End IfEnd Subroutine trl_restart_search_range!!!! try to determine the minimal gap ratio need to compute all wanted! eigenvalues !!!Function trl_min_gap_ratio(info, nd, tind, res) Result(gamma)  Use trl_info  Implicit None  Type(TRL_INFO_T), Intent(in) :: info  Integer, Intent(in) :: nd, tind  Real(8), Intent(in) :: res(nd)  Real(8) :: gamma  !  gamma = info%maxmv * (info%nec + 1.0D0) / info%ned - info%matvec  If (gamma .Lt. info%klan) Then     gamma = Max((info%maxmv-info%matvec)/Dble(info%ned-info%nec), 2.0D0)  End If  gamma = Min(Log(res(tind)/(info%tol*info%anrm))/gamma, 0.5D0)  ReturnEnd Function trl_min_gap_ratio

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?