FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_solver_Iterative.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2019 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
5 
7 contains
8  !
9  !C***
10  !C*** hecmw_solve_nn
11  !C***
12  !
13  subroutine hecmw_solve_iterative (hecMESH, hecMAT)
14 
15  use hecmw_util
16  use hecmw_solver_cg
24  use hecmw_solver_cr
27  use hecmw_precond
31 
32  implicit none
33 
34  type (hecmwST_matrix), target :: hecMAT
35  type (hecmwST_local_mesh) :: hecMESH
36 
37  integer(kind=kint) :: error
38  integer(kind=kint) :: ITER, METHOD, PRECOND, NSET, METHOD2
39  integer(kind=kint) :: iterPREmax
40  integer(kind=kint) :: ITERlog, TIMElog
41  real(kind=kreal) :: resid, sigma_diag, thresh, filter, resid2
42  real(kind=kreal) :: time_setup, time_comm, time_sol, tr
43  real(kind=kreal) :: time_ax, time_precond
44 
45  integer(kind=kint) :: NREST
46  real(kind=kreal) :: sigma
47 
48  integer(kind=kint) :: auto_sigma_diag
49 
50  !C PARAMETERs
51  iter = hecmw_mat_get_iter(hecmat)
52  method = hecmw_mat_get_method(hecmat)
53  method2 = hecmw_mat_get_method2(hecmat)
54  precond = hecmw_mat_get_precond(hecmat)
55  nset = hecmw_mat_get_nset(hecmat)
56  iterpremax= hecmw_mat_get_iterpremax(hecmat)
57  nrest = hecmw_mat_get_nrest(hecmat)
58  iterlog = hecmw_mat_get_iterlog(hecmat)
59  timelog = hecmw_mat_get_timelog(hecmat)
60  time_setup= 0.d0
61  time_comm = 0.d0
62  time_sol = 0.d0
63  resid = hecmw_mat_get_resid(hecmat)
64  sigma_diag= hecmw_mat_get_sigma_diag(hecmat)
65  sigma = hecmw_mat_get_sigma(hecmat)
66  thresh = hecmw_mat_get_thresh(hecmat)
67  filter = hecmw_mat_get_filter(hecmat)
68  if (sigma_diag.lt.0.d0) then
69  auto_sigma_diag= 1
70  sigma_diag= 1.d0
71  else
72  auto_sigma_diag= 0
73  endif
74 
75  !C ERROR CHECK
76  call hecmw_solve_check_zerodiag(hecmesh, hecmat) !C-- ZERO DIAGONAL component
77 
78  !C-- RECYCLE SETTING OF PRECONDITIONER
80 
81  ! exchange diagonal elements of overlap region
82  call hecmw_mat_dump(hecmat, hecmesh)
83 
84  !C ITERATIVE solver
85  error=0
86  !! Auto Sigma_diag loop
87  do
88  call hecmw_mat_set_flag_converged(hecmat, 0)
89  call hecmw_mat_set_flag_diverged(hecmat, 0)
90  if (auto_sigma_diag.eq.1) call hecmw_mat_set_sigma_diag(hecmat, sigma_diag)
91 
94  call hecmw_solve_iterative_printmsg(hecmesh,hecmat,method)
95 
96  select case(method)
97  case (1) !--CG
98  hecmat%symmetric = .true.
99  call hecmw_solve_cg( hecmesh, hecmat, iter, resid, error, time_setup, time_sol, time_comm )
100  case (2) !--BiCGSTAB
101  hecmat%symmetric = .false.
102  call hecmw_solve_bicgstab( hecmesh,hecmat, iter, resid, error,time_setup, time_sol, time_comm )
103  case (3) !--GMRES
104  hecmat%symmetric = .false.
105  call hecmw_solve_gmres( hecmesh,hecmat, iter, resid, error, time_setup, time_sol, time_comm )
106  case (4) !--GPBiCG
107  hecmat%symmetric = .false.
108  call hecmw_solve_gpbicg( hecmesh,hecmat, iter, resid, error, time_setup, time_sol, time_comm )
109  case (5) !--GMRESR
110  hecmat%symmetric = .false.
111  call hecmw_solve_gmresr( hecmesh,hecmat, iter, resid, error, time_setup, time_sol, time_comm )
112  case (6) !--GMRESREN
113  hecmat%symmetric = .false.
114  call hecmw_solve_gmresren( hecmesh,hecmat, iter, resid, error, time_setup, time_sol, time_comm )
115  case (7) !--CR
116  hecmat%symmetric = .true.
117  call hecmw_solve_cr( hecmesh, hecmat, iter, resid, error, time_setup, time_sol, time_comm )
118  case (8) !--PipeCG
119  hecmat%symmetric = .true.
120  call hecmw_solve_pipecg( hecmesh, hecmat, iter, resid, error, time_setup, time_sol, time_comm )
121  case (9) !--GroppCG
122  hecmat%symmetric = .true.
123  call hecmw_solve_groppcg( hecmesh, hecmat, iter, resid, error, time_setup, time_sol, time_comm )
124  case default
125  error = hecmw_solver_error_incons_pc !!未定義なMETHOD!!
126  call hecmw_solve_error (hecmesh, error)
127  end select
128 
130  .or. error==hecmw_solver_error_diverge_nan) then
131  call hecmw_mat_set_flag_diverged(hecmat, 1)
132  if ((precond>=10 .and. precond<20) .and. auto_sigma_diag==1 .and. sigma_diag<2.d0) then
133  sigma_diag = sigma_diag + 0.1
134  if (hecmesh%my_rank.eq.0) write(*,*) 'Increasing SIGMA_DIAG to', sigma_diag
135  cycle
136  elseif ((method==1 .or. method==8 .or. method==9) .and. method2>1) then
137  if (auto_sigma_diag.eq.1) sigma_diag = 1.0
138  method = method2
139  cycle
140  endif
141  endif
142 
143  if (auto_sigma_diag.eq.1) call hecmw_mat_set_sigma_diag(hecmat, -1.d0)
144  exit
145  enddo
146 
147  if (error.ne.0) then
148  call hecmw_solve_error (hecmesh, error)
149  endif
150 
151  resid2=hecmw_rel_resid_l2(hecmesh,hecmat)
152  if (hecmesh%my_rank.eq.0 .and. (iterlog.eq.1 .or. timelog.ge.1)) then
153  write(*,"(a,1pe12.5)")'### Relative residual =', resid2
154  endif
155  if (resid2 < hecmw_mat_get_resid(hecmat)) call hecmw_mat_set_flag_converged(hecmat, 1)
156 
157  call hecmw_mat_dump_solution(hecmat)
158 
159  time_ax = hecmw_matvec_get_timer()
160  time_precond = hecmw_precond_get_timer()
161 
162  if (hecmesh%my_rank.eq.0 .and. timelog.ge.1) then
163  tr= (time_sol-time_comm)/(time_sol+1.d-24)*100.d0
164  write (*,'(/a)') '### summary of linear solver'
165  write (*,'(i10,a, 1pe16.6)') iter, ' iterations ', resid
166  write (*,'(a, 1pe16.6 )') ' set-up time : ', time_setup
167  write (*,'(a, 1pe16.6 )') ' solver time : ', time_sol
168  write (*,'(a, 1pe16.6 )') ' solver/comm time : ', time_comm
169  write (*,'(a, 1pe16.6 )') ' solver/matvec : ', time_ax
170  write (*,'(a, 1pe16.6 )') ' solver/precond : ', time_precond
171  if (iter > 0) &
172  write (*,'(a, 1pe16.6 )') ' solver/1 iter : ', time_sol / iter
173  write (*,'(a, 1pe16.6/)') ' work ratio (%) : ', tr
174  endif
175 
176  call hecmw_output_flops(hecmesh, hecmat, iter, time_ax)
177 
178  end subroutine hecmw_solve_iterative
179 
180  subroutine hecmw_output_flops(hecMESH, hecMAT, count_Ax, time_Ax)
181  use hecmw_util
182  use m_hecmw_comm_f
185  implicit none
186  type (hecmwST_local_mesh) :: hecMESH
187  type(hecmwst_matrix) :: hecMAT
188  integer(kint) :: N, NP, NDOF, NPU, NPL, NZ
189  integer(kint) :: base, i, count_Ax
190  real(kreal) :: time_Ax, size_matrix, flop_matrix, size_vector, memory_size, tmp, num
191  real(kreal) :: t_max, t_min, t_avg, t_sd
192  character(2) :: SI(0:6) = [' ',' K',' M',' G',' T',' P',' E']
193 
194  if(hecmw_mat_get_timelog(hecmat) /= 2) return
195 
196  n = hecmat%N
197  np = hecmat%NP
198  ndof = hecmat%NDOF
199  npu = hecmat%indexU(n)
200  npl = hecmat%indexL(n)
201  nz = n + npu + npl
202 
203  size_matrix = kreal*nz*ndof**2 &
204  + kint*(npu+npl) &
205  + kint*2*(n+1)
206  size_vector = kreal*n*ndof &
207  + kreal*np*ndof
208  memory_size = size_matrix + size_vector
209  flop_matrix = 2.0d0*nz*ndof**2
210 
211  call hecmw_allreduce_r1(hecmesh, memory_size, hecmw_sum)
212  call hecmw_allreduce_r1(hecmesh, flop_matrix, hecmw_sum)
213 
214  base = 1000 ! or 1024
215  num = memory_size
216  i = int(log(num) / log(dble(base)))
217  tmp = 1.0d0/base**i * num
218  if(hecmesh%my_rank == 0)then
219  write (*,"(a,f11.3,a,a)") "memory amount of coef. matrix: ", tmp, si(i),"B"
220  endif
221 
222  num = count_ax*memory_size/time_ax
223  i = int(log(num) / log(dble(base)))
224  tmp = 1.0d0/base**i * num
225  call hecmw_time_statistics(hecmesh, tmp, t_max, t_min, t_avg, t_sd)
226  if(hecmesh%my_rank == 0)then
227  write(*,"(a,f11.3,a,a)") "matvec memory band width : ", tmp, si(i),"B/s"
228  write(*,"(a,f11.3)") ' Max :',t_max
229  write(*,"(a,f11.3)") ' Min :',t_min
230  write(*,"(a,f11.3)") ' Avg :',t_avg
231  write(*,"(a,f11.3)") ' Std Dev :',t_sd
232  endif
233 
234  num = count_ax*flop_matrix/time_ax
235  i = int(log(num) / log(dble(base)))
236  tmp = 1.0d0/base**i * num
237  call hecmw_time_statistics(hecmesh, tmp, t_max, t_min, t_avg, t_sd)
238  if(hecmesh%my_rank == 0)then
239  write(*,"(a,f11.3,a,a)") "matvec FLOPs : ", tmp, si(i),"FLOPs"
240  write(*,"(a,f11.3)") ' Max :',t_max
241  write(*,"(a,f11.3)") ' Min :',t_min
242  write(*,"(a,f11.3)") ' Avg :',t_avg
243  write(*,"(a,f11.3)") ' Std Dev :',t_sd
244  endif
245  end subroutine hecmw_output_flops
246 
247  subroutine hecmw_solve_check_zerodiag (hecMESH, hecMAT)
248  use hecmw_util
251  use m_hecmw_comm_f
252  implicit none
253  type (hecmwST_local_mesh) :: hecMESH
254  type (hecmwST_matrix), target :: hecMAT
255  integer (kind=kint)::PRECOND,iterPREmax,i,j,error
256  precond = hecmw_mat_get_precond(hecmat)
257  iterpremax= hecmw_mat_get_iterpremax(hecmat)
258  !C
259  !C-- ZERO DIAGONAL component
260  error= 0
261  do i= 1, hecmat%N
262  do j = 1, hecmat%NDOF
263  if (dabs(hecmat%D(hecmat%NDOF*hecmat%NDOF*(i-1)+(j-1)*(hecmat%NDOF+1)+1)).eq.0.d0) then
265  end if
266  end do
267  enddo
268 
269  call hecmw_allreduce_i1 (hecmesh, error, hecmw_max)
270  if (error.ne.0 .and. (precond.lt.10 .and. iterpremax.gt.0)) then
271  call hecmw_solve_error (hecmesh, error)
272  endif
273 
274  end subroutine hecmw_solve_check_zerodiag
275 
276  function hecmw_solve_check_zerorhs (hecMESH, hecMAT)
277  use hecmw_util
280  use m_hecmw_comm_f
281  implicit none
282  type (hecmwst_local_mesh) :: hecmesh
283  type (hecmwst_matrix), target :: hecmat
284  real(kind=kreal), dimension(1) :: rhs
285  integer (kind=kint)::precond,iterpremax,i,j,error
286  logical :: hecmw_solve_check_zerorhs
287 
288  precond = hecmw_mat_get_precond(hecmat)
289  iterpremax= hecmw_mat_get_iterpremax(hecmat)
290  !C
291  !C-- ZERO RHS norm
292  error= 0
293  hecmw_solve_check_zerorhs = .false.
294 
295  rhs(1)= 0.d0
296  do i= 1, hecmat%N
297  do j = 1, hecmat%NDOF
298  rhs(1)=rhs(1) + hecmat%B(hecmat%NDOF*(i-1)+j)**2
299  end do
300  enddo
301  if (hecmesh%mpc%n_mpc > 0) then
302  do i= 1, hecmesh%mpc%n_mpc
303  rhs(1)= rhs(1) + hecmesh%mpc%mpc_const(i)**2
304  enddo
305  endif
306  call hecmw_allreduce_r (hecmesh, rhs, 1, hecmw_sum)
307 
308  if (rhs(1).eq.0.d0) then
310  call hecmw_solve_error (hecmesh, error)
311  hecmat%X(:)=0.d0
313  endif
314 
315  end function hecmw_solve_check_zerorhs
316 
317  subroutine hecmw_solve_iterative_printmsg (hecMESH, hecMAT, METHOD)
318  use hecmw_util
321 
322  implicit none
323  type (hecmwST_local_mesh) :: hecMESH
324  type (hecmwST_matrix), target :: hecMAT
325  integer(kind=kint) :: METHOD
326  integer(kind=kint) :: ITER, PRECOND, NSET, iterPREmax, NREST,NBFGS
327  integer(kind=kint) :: ITERlog, TIMElog
328 
329  character(len=30) :: msg_precond
330  character(len=30) :: msg_method
331 
332  iter = hecmw_mat_get_iter(hecmat)
333  ! METHOD = hecmw_mat_get_method(hecMAT)
334  precond = hecmw_mat_get_precond(hecmat)
335  nset = hecmw_mat_get_nset(hecmat)
336  iterpremax= hecmw_mat_get_iterpremax(hecmat)
337  nrest = hecmw_mat_get_nrest(hecmat)
338  nbfgs = hecmw_mat_get_nbfgs(hecmat)
339  iterlog= hecmw_mat_get_iterlog(hecmat)
340  timelog= hecmw_mat_get_timelog(hecmat)
341 
342  select case(method)
343  case (1) !--CG
344  msg_method="CG"
345  case (2) !--BiCGSTAB
346  msg_method="BiCGSTAB"
347  case (3) !--GMRES
348  msg_method="GMRES"
349  case (4) !--GPBiCG
350  msg_method="GPBiCG"
351  case (5)
352  if (nbfgs==0) then
353  msg_method="GMRESR"
354  else
355  msg_method="SUP-GMRESR"
356  endif
357  case (6)
358  msg_method="GMRESR-EN"
359  case (7) !--CR
360  msg_method="CR"
361  case (8) !--PipeCG
362  msg_method="PipeCG"
363  case (9) !--GroppCG
364  msg_method="GroppCG"
365  case default
366  msg_method="Unlabeled"
367  end select
368  select case(precond)
369  case (1,2)
370  msg_precond="SSOR"
371  case (3)
372  msg_precond="DIAG"
373  case (5)
374  msg_precond="ML"
375  case (7)
376  msg_precond="DirectMUMPS"
377  case (10, 11, 12)
378  write(msg_precond,"(a,i0,a)") "ILU(",precond-10,")"
379  case (20)
380  msg_precond="SAINV"
381  case (21)
382  msg_precond="RIF"
383  case (22)
384  msg_precond="SAAMG"
385  case default
386  msg_precond="Unlabeled"
387  end select
388  if (hecmesh%my_rank.eq.0 .and. (iterlog.eq.1 .or. timelog.ge.1)) then
389  write (*,'(a,i0,a,i0,a,a,a,a,a,i0)') '### ',hecmat%NDOF,'x',hecmat%NDOF,' BLOCK ', &
390  & trim(msg_method),", ",trim(msg_precond),", ", iterpremax
391  end if
392  end subroutine hecmw_solve_iterative_printmsg
393 
394 end module hecmw_solver_iterative
subroutine, public hecmw_mat_dump(hecMAT, hecMESH)
subroutine, public hecmw_mat_dump_solution(hecMAT)
real(kind=kreal) function, public hecmw_mat_get_sigma_diag(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_iterpremax(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_nrest(hecMAT)
subroutine, public hecmw_mat_set_flag_diverged(hecMAT, flag_diverged)
real(kind=kreal) function, public hecmw_mat_get_resid(hecMAT)
subroutine, public hecmw_mat_set_flag_converged(hecMAT, flag_converged)
integer(kind=kint) function, public hecmw_mat_get_nbfgs(hecMAT)
subroutine, public hecmw_mat_recycle_precond_setting(hecMAT)
subroutine, public hecmw_mat_set_sigma_diag(hecMAT, sigma_diag)
integer(kind=kint) function, public hecmw_mat_get_iterlog(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_timelog(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_method2(hecMAT)
real(kind=kreal) function, public hecmw_mat_get_thresh(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_method(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_precond(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_nset(hecMAT)
real(kind=kreal) function, public hecmw_mat_get_filter(hecMAT)
real(kind=kreal) function, public hecmw_mat_get_sigma(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_iter(hecMAT)
subroutine, public hecmw_precond_clear_timer
real(kind=kreal) function, public hecmw_precond_get_timer()
subroutine hecmw_solve_bicgstab(hecMESH, hecMAT, ITER, RESID, error, Tset, Tsol, Tcomm)
subroutine, public hecmw_solve_cg(hecMESH, hecMAT, ITER, RESID, error, Tset, Tsol, Tcomm)
subroutine, public hecmw_solve_cr(hecMESH, hecMAT, ITER, RESID, error, Tset, Tsol, Tcomm)
subroutine, public hecmw_solve_gmres(hecMESH, hecMAT, ITER, RESID, error, Tset, Tsol, Tcomm)
subroutine, public hecmw_solve_gmresr(hecMESH, hecMAT, ITER, RESID, error, Tset, Tsol, Tcomm)
subroutine, public hecmw_solve_gmresren(hecMESH, hecMAT, ITER, RESID, error, Tset, Tsol, Tcomm)
subroutine, public hecmw_solve_gpbicg(hecMESH, hecMAT, ITER, RESID, error, Tset, Tsol, Tcomm)
subroutine, public hecmw_solve_groppcg(hecMESH, hecMAT, ITER, RESID, error, Tset, Tsol, Tcomm)
subroutine hecmw_solve_iterative_printmsg(hecMESH, hecMAT, METHOD)
subroutine hecmw_output_flops(hecMESH, hecMAT, count_Ax, time_Ax)
logical function hecmw_solve_check_zerorhs(hecMESH, hecMAT)
subroutine hecmw_solve_check_zerodiag(hecMESH, hecMAT)
subroutine hecmw_solve_iterative(hecMESH, hecMAT)
subroutine, public hecmw_matvec_clear_timer
real(kind=kreal) function, public hecmw_rel_resid_l2(hecMESH, hecMAT, COMMtime)
real(kind=kreal) function, public hecmw_matvec_get_timer()
subroutine hecmw_time_statistics(hecMESH, time, t_max, t_min, t_avg, t_sd)
subroutine, public hecmw_solve_pipecg(hecMESH, hecMAT, ITER, RESID, error, Tset, Tsol, Tcomm)
I/O and Utility.
Definition: hecmw_util_f.F90:7
integer(kind=kint), parameter hecmw_sum
integer(kind=4), parameter kint
integer(kind=kint), parameter hecmw_max
integer(kind=4), parameter kreal
subroutine hecmw_allreduce_i1(hecMESH, s, ntag)
subroutine hecmw_allreduce_r(hecMESH, val, n, ntag)
subroutine hecmw_allreduce_r1(hecMESH, s, ntag)
integer(kind=kint), parameter hecmw_solver_error_diverge_pc
integer(kind=kint), parameter hecmw_solver_error_diverge_nan
integer(kind=kint), parameter hecmw_solver_error_incons_pc
integer(kind=kint), parameter hecmw_solver_error_zero_diag
integer(kind=kint), parameter hecmw_solver_error_zero_rhs
subroutine hecmw_solve_error(hecMESH, IFLAG)
integer(kind=kint), parameter hecmw_solver_error_diverge_mat