| 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
|