hecmw_solver_CG_33.f90
   1 
!======================================================================!
   2 
!                                                                      !
   3 
!   Software Name : HEC-MW Library for PC-cluster                      !
   4 
!         Version : 2.7                                                !
   5 
!                                                                      !
   6 
!     Last Update : 2014/12/14                                         !
   7 
!        Category : Linear Solver                                      !
   8 
!                                                                      !
   9 
!            Written by Kengo Nakajima (Univ. of Tokyo)                !
  10 
!                       Kazuya Goto (PExProCS LLC)                     !
  11 
!                                                                      !
  12 
!     Contact address :  IIS,The University of Tokyo RSS21 project     !
  13 
!                                                                      !
  14 
!     "Structural Analysis System for General-purpose Coupling         !
  15 
!      Simulations Using High End Computing Middleware (HEC-MW)"       !
  16 
!                                                                      !
  17 
!======================================================================!
  18 
 
  19 
!C
  20 
!C***
  21 
!C*** module hecmw_solver_CG_33
  22 
!C***
  23 
!C
  24 
      module hecmw_solver_CG_33
  25 
 
  26 
      public :: hecmw_solve_CG_33
  27 
 
  28 
      contains
  29 
!C
  30 
!C*** CG_33
  31 
!C
  32 
      subroutine hecmw_solve_CG_33( hecMESH,  hecMAT, ITER, RESID, ERROR, &
  33 
     &                              Tset, Tsol, Tcomm )
  34 
 
  35 
      use hecmw_util
  36 
      use m_hecmw_solve_error
  37 
      use m_hecmw_comm_f
  38 
      use hecmw_matrix_misc
  39 
      use hecmw_solver_misc
  40 
      use hecmw_solver_las_33
  41 
      use hecmw_solver_scaling_33
  42 
      use hecmw_precond_33
  43 
      use hecmw_jad_type
  44 
      use hecmw_estimate_condition
  45 
 
  46 
      implicit none
  47 
 
  48 
      type(hecmwST_local_mesh) :: hecMESH
  49 
      type(hecmwST_matrix) :: hecMAT
  50 
      integer(kind=kint ), intent(inout):: ITER, ERROR
  51 
      real   (kind=kreal), intent(inout):: RESID, Tset, Tsol, Tcomm
  52 
 
  53 
      integer(kind=kint ) :: N, NP, NDOF, NNDOF
  54 
      integer(kind=kint ) :: my_rank
  55 
      integer(kind=kint ) :: ITERlog, TIMElog
  56 
      real(kind=kreal), pointer :: B(:), X(:)
  57 
 
  58 
      real(kind=kreal), dimension(:,:), allocatable :: WW
  59 
 
  60 
      integer(kind=kint), parameter ::  R= 1
  61 
      integer(kind=kint), parameter ::  Z= 2
  62 
      integer(kind=kint), parameter ::  Q= 2
  63 
      integer(kind=kint), parameter ::  P= 3
  64 
      integer(kind=kint), parameter :: WK= 4
  65 
 
  66 
      integer(kind=kint ) :: MAXIT
  67 
 
  68 
! local variables
  69 
      real   (kind=kreal) :: TOL
  70 
      integer(kind=kint )::i
  71 
      real   (kind=kreal)::S_TIME,S1_TIME,E_TIME,E1_TIME, START_TIME, END_TIME
  72 
      real   (kind=kreal)::BNRM2
  73 
      real   (kind=kreal)::RHO,RHO1,BETA,C1,ALPHA,DNRM2
  74 
      real   (kind=kreal)::t_max,t_min,t_avg,t_sd
  75 
      integer(kind=kint) ::ESTCOND
  76 
      real   (kind=kreal), allocatable::D(:),E(:)
  77 
      real   (kind=kreal)::ALPHA1
  78 
      integer(kind=kint) :: n_indef_precond
  79 
 
  80 
      integer(kind=kint), parameter :: N_ITER_RECOMPUTE_R= 50
  81 
 
  82 
      call hecmw_barrier(hecMESH)
  83 
      S_TIME= HECMW_WTIME()
  84 
 
  85 
!C===
  86 
!C +-------+
  87 
!C | INIT. |
  88 
!C +-------+
  89 
!C===
  90 
      N = hecMAT%N
  91 
      NP = hecMAT%NP
  92 
      NDOF = hecMAT%NDOF
  93 
      NNDOF = N * NDOF
  94 
      my_rank = hecMESH%my_rank
  95 
      X => hecMAT%X
  96 
      B => hecMAT%B
  97 
 
  98 
      ITERlog = hecmw_mat_get_iterlog( hecMAT )
  99 
      TIMElog = hecmw_mat_get_timelog( hecMAT )
 100 
      MAXIT  = hecmw_mat_get_iter( hecMAT )
 101 
      TOL   = hecmw_mat_get_resid( hecMAT )
 102 
      ESTCOND = hecmw_mat_get_estcond( hecMAT )
 103 
 
 104 
      ERROR = 0
 105 
      n_indef_precond = 0
 106 
 
 107 
      allocate (WW(NDOF*NP, 4))
 108 
      WW = 0.d0
 109 
 
 110 
!C
 111 
!C-- SCALING
 112 
      call hecmw_solver_scaling_fw_33(hecMESH, hecMAT, Tcomm)
 113 
 
 114 
      IF (hecmw_mat_get_usejad(hecMAT).ne.0) THEN
 115 
        call hecmw_JAD_INIT(hecMAT)
 116 
      ENDIF
 117 
 
 118 
      if (ESTCOND /= 0 .and. hecMESH%my_rank == 0) then
 119 
        allocate(D(MAXIT),E(MAXIT-1))
 120 
      endif
 121 
!C===
 122 
!C +----------------------+
 123 
!C | SETUP PRECONDITIONER |
 124 
!C +----------------------+
 125 
!C===
 126 
      call hecmw_precond_33_setup(hecMAT, hecMESH, 1)
 127 
 
 128 
!C===
 129 
!C +---------------------+
 130 
!C | {r0}= {b} - [A]{x0} |
 131 
!C +---------------------+
 132 
!C===
 133 
      call hecmw_matresid_33(hecMESH, hecMAT, X, B, WW(:,R), Tcomm)
 134 
 
 135 
!C-- compute ||{b}||
 136 
      call hecmw_InnerProduct_R(hecMESH, NDOF, B, B, BNRM2, Tcomm)
 137 
      if (BNRM2.eq.0.d0) then
 138 
        iter = 0
 139 
        MAXIT = 0
 140 
        RESID = 0.d0
 141 
        X = 0.d0
 142 
      endif
 143 
 
 144 
      E_TIME = HECMW_WTIME()
 145 
      if (TIMElog.eq.2) then
 146 
        call hecmw_time_statistics(hecMESH, E_TIME - S_TIME, &
 147 
             t_max, t_min, t_avg, t_sd)
 148 
        if (hecMESH%my_rank.eq.0) then
 149 
          write(*,*) 'Time solver setup'
 150 
          write(*,*) '  Max     :',t_max
 151 
          write(*,*) '  Min     :',t_min
 152 
          write(*,*) '  Avg     :',t_avg
 153 
          write(*,*) '  Std Dev :',t_sd
 154 
        endif
 155 
        Tset = t_max
 156 
      else
 157 
        Tset = E_TIME - S_TIME
 158 
      endif
 159 
 
 160 
      Tcomm = 0.d0
 161 
      call hecmw_barrier(hecMESH)
 162 
      S1_TIME = HECMW_WTIME()
 163 
!C
 164 
!C************************************************* Conjugate Gradient Iteration start
 165 
!C
 166 
      do iter = 1, MAXIT
 167 
 
 168 
!C===
 169 
!C +----------------+
 170 
!C | {z}= [Minv]{r} |
 171 
!C +----------------+
 172 
!C===
 173 
      call hecmw_precond_33_apply(hecMESH, hecMAT, WW(:,R), WW(:,Z), WW(:,WK), Tcomm)
 174 
 
 175 
!C===
 176 
!C +---------------+
 177 
!C | {RHO}= {r}{z} |
 178 
!C +---------------+
 179 
!C===
 180 
      call hecmw_InnerProduct_R(hecMESH, NDOF, WW(:,R), WW(:,Z), RHO, Tcomm)
 181 
      ! if RHO is NaN or Inf then no converge
 182 
      if (RHO == 0.d0) then
 183 
        ! converged due to RHO==0
 184 
        exit
 185 
      elseif (iter > 1 .and. RHO*RHO1 <= 0) then
 186 
        n_indef_precond = n_indef_precond + 1
 187 
        if (n_indef_precond >= 3) then
 188 
          ! diverged due to indefinite preconditioner
 189 
          ERROR = HECMW_SOLVER_ERROR_DIVERGE_PC
 190 
          exit
 191 
        endif
 192 
      endif
 193 
 
 194 
!C===
 195 
!C +-----------------------------+
 196 
!C | {p} = {z} if      ITER=1    |
 197 
!C | BETA= RHO / RHO1  otherwise |
 198 
!C +-----------------------------+
 199 
!C===
 200 
      if ( ITER.eq.1 ) then
 201 
        do i = 1, NNDOF
 202 
          WW(i,P) = WW(i,Z)
 203 
        enddo
 204 
       else
 205 
         BETA = RHO / RHO1
 206 
         do i = 1, NNDOF
 207 
           WW(i,P) = WW(i,Z) + BETA*WW(i,P)
 208 
         enddo
 209 
      endif
 210 
 
 211 
!C===
 212 
!C +--------------+
 213 
!C | {q}= [A] {p} |
 214 
!C +--------------+
 215 
!C===
 216 
      call hecmw_matvec_33(hecMESH, hecMAT, WW(:,P), WW(:,Q), Tcomm)
 217 
 
 218 
!C===
 219 
!C +---------------------+
 220 
!C | ALPHA= RHO / {p}{q} |
 221 
!C +---------------------+
 222 
!C===
 223 
      call hecmw_InnerProduct_R(hecMESH, NDOF, WW(:,P), WW(:,Q), C1, Tcomm)
 224 
      ! if C1 is NaN or Inf, no converge
 225 
      if (C1 <= 0) then
 226 
        ! diverged due to indefinite or negative definite matrix
 227 
        ERROR = HECMW_SOLVER_ERROR_DIVERGE_MAT
 228 
        exit
 229 
      endif
 230 
 
 231 
      ALPHA= RHO / C1
 232 
 
 233 
!C===
 234 
!C +----------------------+
 235 
!C | {x}= {x} + ALPHA*{p} |
 236 
!C | {r}= {r} - ALPHA*{q} |
 237 
!C +----------------------+
 238 
!C===
 239 
      do i = 1, NNDOF
 240 
         X(i)  = X(i)    + ALPHA * WW(i,P)
 241 
        ! WW(i,R)= WW(i,R) - ALPHA * WW(i,Q)
 242 
      enddo
 243 
 
 244 
      if ( mod(ITER,N_ITER_RECOMPUTE_R)==0 ) then
 245 
        call hecmw_matresid_33(hecMESH, hecMAT, X, B, WW(:,R), Tcomm)
 246 
      else
 247 
        do i = 1, NNDOF
 248 
          WW(i,R)= WW(i,R) - ALPHA * WW(i,Q)
 249 
        enddo
 250 
      endif
 251 
 
 252 
      call hecmw_InnerProduct_R(hecMESH, NDOF, WW(:,R), WW(:,R), DNRM2, Tcomm)
 253 
 
 254 
      RESID= dsqrt(DNRM2/BNRM2)
 255 
 
 256 
!C##### ITERATION HISTORY
 257 
      if (my_rank.eq.0.and.ITERLog.eq.1) write (*,'(i7, 1pe16.6)') ITER, RESID
 258 
!C#####
 259 
 
 260 
      if (ESTCOND /= 0 .and. hecMESH%my_rank == 0) then
 261 
        if (ITER == 1) then
 262 
          D(1) = 1.d0 / ALPHA
 263 
        else
 264 
          D(ITER) = 1.d0 / ALPHA + BETA / ALPHA1
 265 
          E(ITER-1) = sqrt(BETA) / ALPHA1
 266 
        endif
 267 
        ALPHA1 = ALPHA
 268 
        if (mod(ITER,ESTCOND) == 0) call hecmw_estimate_condition_CG(ITER, D, E)
 269 
      endif
 270 
 
 271 
      if ( RESID.le.TOL   ) then
 272 
        if ( mod(ITER,N_ITER_RECOMPUTE_R)==0 ) exit
 273 
!C----- recompute R to make sure it is really converged
 274 
        call hecmw_matresid_33(hecMESH, hecMAT, X, B, WW(:,R), Tcomm)
 275 
        call hecmw_InnerProduct_R(hecMESH, NDOF, WW(:,R), WW(:,R), DNRM2, Tcomm)
 276 
        RESID= dsqrt(DNRM2/BNRM2)
 277 
        if ( RESID.le.TOL ) exit
 278 
      endif
 279 
      if ( ITER .eq.MAXIT ) ERROR = HECMW_SOLVER_ERROR_NOCONV_MAXIT
 280 
 
 281 
      RHO1 = RHO
 282 
 
 283 
      enddo
 284 
!C
 285 
!C************************************************* Conjugate Gradient Iteration end
 286 
!C
 287 
      call hecmw_solver_scaling_bk_33(hecMAT)
 288 
!C
 289 
!C-- INTERFACE data EXCHANGE
 290 
!C
 291 
      START_TIME= HECMW_WTIME()
 292 
      call hecmw_update_3_R (hecMESH, X, hecMAT%NP)
 293 
      END_TIME = HECMW_WTIME()
 294 
      Tcomm = Tcomm + END_TIME - START_TIME
 295 
 
 296 
      deallocate (WW)
 297 
      !call hecmw_precond_33_clear(hecMAT)
 298 
 
 299 
      IF (hecmw_mat_get_usejad(hecMAT).ne.0) THEN
 300 
        call hecmw_JAD_FINALIZE()
 301 
      ENDIF
 302 
 
 303 
      if (ESTCOND /= 0 .and. ERROR == 0 .and. hecMESH%my_rank == 0) then
 304 
        call hecmw_estimate_condition_CG(ITER, D, E)
 305 
        deallocate(D, E)
 306 
      endif
 307 
 
 308 
      E1_TIME = HECMW_WTIME()
 309 
      if (TIMElog.eq.2) then
 310 
        call hecmw_time_statistics(hecMESH, E1_TIME - S1_TIME, &
 311 
             t_max, t_min, t_avg, t_sd)
 312 
        if (hecMESH%my_rank.eq.0) then
 313 
          write(*,*) 'Time solver iterations'
 314 
          write(*,*) '  Max     :',t_max
 315 
          write(*,*) '  Min     :',t_min
 316 
          write(*,*) '  Avg     :',t_avg
 317 
          write(*,*) '  Std Dev :',t_sd
 318 
        endif
 319 
        Tsol = t_max
 320 
      else
 321 
        Tsol = E1_TIME - S1_TIME
 322 
      endif
 323 
 
 324 
      end subroutine hecmw_solve_CG_33
 325 
 
 326 
      end module     hecmw_solver_CG_33