FrontISTR  6.0.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) :: omega
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  thresh = hecmw_mat_get_thresh(hecmat)
66  filter = hecmw_mat_get_filter(hecmat)
67  if (sigma_diag.lt.0.d0) then
68  auto_sigma_diag= 1
69  sigma_diag= 1.d0
70  else
71  auto_sigma_diag= 0
72  endif
73 
74  ! the control file reaches Rarray without passing through the setter, so the
75  ! range that hecmw_mat_set_omega enforces has to be applied here as well
76  omega = hecmw_mat_get_omega(hecmat)
77  call hecmw_mat_set_omega(hecmat, omega)
78 
79  !C ERROR CHECK
80  call hecmw_solve_check_zerodiag(hecmesh, hecmat) !C-- ZERO DIAGONAL component
81 
82  !C-- RECYCLE SETTING OF PRECONDITIONER
84 
85  ! exchange diagonal elements of overlap region
86  call hecmw_mat_dump(hecmat, hecmesh)
87 
88  !C ITERATIVE solver
89  error=0
90  !! Auto Sigma_diag loop
91  do
92  call hecmw_mat_set_flag_converged(hecmat, 0)
93  call hecmw_mat_set_flag_diverged(hecmat, 0)
94  if (auto_sigma_diag.eq.1) call hecmw_mat_set_sigma_diag(hecmat, sigma_diag)
95 
98  call hecmw_solve_iterative_printmsg(hecmesh,hecmat,method)
99 
100  select case(method)
101  case (1) !--CG
102  hecmat%symmetric = .true.
103  call hecmw_solve_cg( hecmesh, hecmat, iter, resid, error, time_setup, time_sol, time_comm )
104  case (2) !--BiCGSTAB
105  hecmat%symmetric = .false.
106  call hecmw_solve_bicgstab( hecmesh,hecmat, iter, resid, error,time_setup, time_sol, time_comm )
107  case (3) !--GMRES
108  hecmat%symmetric = .false.
109  call hecmw_solve_gmres( hecmesh,hecmat, iter, resid, error, time_setup, time_sol, time_comm )
110  case (4) !--GPBiCG
111  hecmat%symmetric = .false.
112  call hecmw_solve_gpbicg( hecmesh,hecmat, iter, resid, error, time_setup, time_sol, time_comm )
113  case (5) !--GMRESR
114  hecmat%symmetric = .false.
115  call hecmw_solve_gmresr( hecmesh,hecmat, iter, resid, error, time_setup, time_sol, time_comm )
116  case (6) !--GMRESREN
117  hecmat%symmetric = .false.
118  call hecmw_solve_gmresren( hecmesh,hecmat, iter, resid, error, time_setup, time_sol, time_comm )
119  case (7) !--CR
120  hecmat%symmetric = .true.
121  call hecmw_solve_cr( hecmesh, hecmat, iter, resid, error, time_setup, time_sol, time_comm )
122  case (8) !--PipeCG
123  hecmat%symmetric = .true.
124  call hecmw_solve_pipecg( hecmesh, hecmat, iter, resid, error, time_setup, time_sol, time_comm )
125  case (9) !--GroppCG
126  hecmat%symmetric = .true.
127  call hecmw_solve_groppcg( hecmesh, hecmat, iter, resid, error, time_setup, time_sol, time_comm )
128  case default
129  error = hecmw_solver_error_incons_pc !!未定義なMETHOD!!
130  call hecmw_solve_error (hecmesh, error)
131  end select
132 
134  .or. error==hecmw_solver_error_diverge_nan) then
135  call hecmw_mat_set_flag_diverged(hecmat, 1)
136  if ((precond>=10 .and. precond<20) .and. auto_sigma_diag==1 .and. sigma_diag<2.d0) then
137  sigma_diag = sigma_diag + 0.1
138  if (hecmesh%my_rank.eq.0) write(*,*) 'Increasing SIGMA_DIAG to', sigma_diag
139  cycle
140  elseif ((method==1 .or. method==8 .or. method==9) .and. method2>1) then
141  if (auto_sigma_diag.eq.1) sigma_diag = 1.0
142  method = method2
143  cycle
144  endif
145  endif
146 
147  if (auto_sigma_diag.eq.1) call hecmw_mat_set_sigma_diag(hecmat, -1.d0)
148  exit
149  enddo
150 
151  if (error.ne.0) then
152  call hecmw_solve_error (hecmesh, error)
153  endif
154 
155  resid2=hecmw_rel_resid_l2(hecmesh,hecmat)
156  if (hecmesh%my_rank.eq.0 .and. (iterlog.eq.1 .or. timelog.ge.1)) then
157  write(*,"(a,1pe12.5)")'### Relative residual =', resid2
158  endif
159  if (resid2 < hecmw_mat_get_resid(hecmat)) call hecmw_mat_set_flag_converged(hecmat, 1)
160 
161  call hecmw_mat_dump_solution(hecmat)
162 
163  time_ax = hecmw_matvec_get_timer()
164  time_precond = hecmw_precond_get_timer()
165 
166  if (hecmesh%my_rank.eq.0 .and. timelog.ge.1) then
167  tr= (time_sol-time_comm)/(time_sol+1.d-24)*100.d0
168  write (*,'(/a)') '### summary of linear solver'
169  write (*,'(i10,a, 1pe16.6)') iter, ' iterations ', resid
170  write (*,'(a, 1pe16.6 )') ' set-up time : ', time_setup
171  write (*,'(a, 1pe16.6 )') ' solver time : ', time_sol
172  write (*,'(a, 1pe16.6 )') ' solver/comm time : ', time_comm
173  write (*,'(a, 1pe16.6 )') ' solver/matvec : ', time_ax
174  write (*,'(a, 1pe16.6 )') ' solver/precond : ', time_precond
175  if (iter > 0) &
176  write (*,'(a, 1pe16.6 )') ' solver/1 iter : ', time_sol / iter
177  write (*,'(a, 1pe16.6/)') ' work ratio (%) : ', tr
178  endif
179 
180  call hecmw_output_flops(hecmesh, hecmat, iter, time_ax)
181 
182  end subroutine hecmw_solve_iterative
183 
184  subroutine hecmw_output_flops(hecMESH, hecMAT, count_Ax, time_Ax)
185  use hecmw_util
186  use m_hecmw_comm_f
189  implicit none
190  type (hecmwST_local_mesh) :: hecMESH
191  type(hecmwst_matrix) :: hecMAT
192  integer(kint) :: N, NP, NDOF, NPU, NPL, NZ
193  integer(kint) :: base, i, count_Ax
194  real(kreal) :: time_Ax, size_matrix, flop_matrix, size_vector, memory_size, tmp, num
195  real(kreal) :: t_max, t_min, t_avg, t_sd
196  character(2) :: SI(0:6) = [' ',' K',' M',' G',' T',' P',' E']
197 
198  if(hecmw_mat_get_timelog(hecmat) /= 2) return
199 
200  n = hecmat%N
201  np = hecmat%NP
202  ndof = hecmat%NDOF
203  npu = hecmat%indexU(n)
204  npl = hecmat%indexL(n)
205  nz = n + npu + npl
206 
207  size_matrix = kreal*nz*ndof**2 &
208  + kint*(npu+npl) &
209  + kint*2*(n+1)
210  size_vector = kreal*n*ndof &
211  + kreal*np*ndof
212  memory_size = size_matrix + size_vector
213  flop_matrix = 2.0d0*nz*ndof**2
214 
215  call hecmw_allreduce_r1(hecmesh, memory_size, hecmw_sum)
216  call hecmw_allreduce_r1(hecmesh, flop_matrix, hecmw_sum)
217 
218  base = 1000 ! or 1024
219  num = memory_size
220  i = int(log(num) / log(dble(base)))
221  tmp = 1.0d0/base**i * num
222  if(hecmesh%my_rank == 0)then
223  write (*,"(a,f11.3,a,a)") "memory amount of coef. matrix: ", tmp, si(i),"B"
224  endif
225 
226  num = count_ax*memory_size/time_ax
227  i = int(log(num) / log(dble(base)))
228  tmp = 1.0d0/base**i * num
229  call hecmw_time_statistics(hecmesh, tmp, t_max, t_min, t_avg, t_sd)
230  if(hecmesh%my_rank == 0)then
231  write(*,"(a,f11.3,a,a)") "matvec memory band width : ", tmp, si(i),"B/s"
232  write(*,"(a,f11.3)") ' Max :',t_max
233  write(*,"(a,f11.3)") ' Min :',t_min
234  write(*,"(a,f11.3)") ' Avg :',t_avg
235  write(*,"(a,f11.3)") ' Std Dev :',t_sd
236  endif
237 
238  num = count_ax*flop_matrix/time_ax
239  i = int(log(num) / log(dble(base)))
240  tmp = 1.0d0/base**i * num
241  call hecmw_time_statistics(hecmesh, tmp, t_max, t_min, t_avg, t_sd)
242  if(hecmesh%my_rank == 0)then
243  write(*,"(a,f11.3,a,a)") "matvec FLOPs : ", tmp, si(i),"FLOPs"
244  write(*,"(a,f11.3)") ' Max :',t_max
245  write(*,"(a,f11.3)") ' Min :',t_min
246  write(*,"(a,f11.3)") ' Avg :',t_avg
247  write(*,"(a,f11.3)") ' Std Dev :',t_sd
248  endif
249  end subroutine hecmw_output_flops
250 
251  subroutine hecmw_solve_check_zerodiag (hecMESH, hecMAT)
252  use hecmw_util
255  use m_hecmw_comm_f
256  implicit none
257  type (hecmwST_local_mesh) :: hecMESH
258  type (hecmwST_matrix), target :: hecMAT
259  integer (kind=kint)::PRECOND,iterPREmax,i,j,error
260  precond = hecmw_mat_get_precond(hecmat)
261  iterpremax= hecmw_mat_get_iterpremax(hecmat)
262  !C
263  !C-- ZERO DIAGONAL component
264  error= 0
265  do i= 1, hecmat%N
266  do j = 1, hecmat%NDOF
267  if (dabs(hecmat%D(hecmat%NDOF*hecmat%NDOF*(i-1)+(j-1)*(hecmat%NDOF+1)+1)).eq.0.d0) then
269  end if
270  end do
271  enddo
272 
273  call hecmw_allreduce_i1 (hecmesh, error, hecmw_max)
274  if (error.ne.0 .and. (precond.lt.10 .and. iterpremax.gt.0)) then
275  call hecmw_solve_error (hecmesh, error)
276  endif
277 
278  end subroutine hecmw_solve_check_zerodiag
279 
280  function hecmw_solve_check_zerorhs (hecMESH, hecMAT)
281  use hecmw_util
284  use m_hecmw_comm_f
285  implicit none
286  type (hecmwst_local_mesh) :: hecmesh
287  type (hecmwst_matrix), target :: hecmat
288  real(kind=kreal), dimension(1) :: rhs
289  integer (kind=kint)::precond,iterpremax,i,j,error
290  logical :: hecmw_solve_check_zerorhs
291 
292  precond = hecmw_mat_get_precond(hecmat)
293  iterpremax= hecmw_mat_get_iterpremax(hecmat)
294  !C
295  !C-- ZERO RHS norm
296  error= 0
297  hecmw_solve_check_zerorhs = .false.
298 
299  rhs(1)= 0.d0
300  do i= 1, hecmat%N
301  do j = 1, hecmat%NDOF
302  rhs(1)=rhs(1) + hecmat%B(hecmat%NDOF*(i-1)+j)**2
303  end do
304  enddo
305  if (hecmesh%mpc%n_mpc > 0) then
306  do i= 1, hecmesh%mpc%n_mpc
307  rhs(1)= rhs(1) + hecmesh%mpc%mpc_const(i)**2
308  enddo
309  endif
310  call hecmw_allreduce_r (hecmesh, rhs, 1, hecmw_sum)
311 
312  if (rhs(1).eq.0.d0) then
314  call hecmw_solve_error (hecmesh, error)
315  hecmat%X(:)=0.d0
317  endif
318 
319  end function hecmw_solve_check_zerorhs
320 
321  subroutine hecmw_solve_iterative_printmsg (hecMESH, hecMAT, METHOD)
322  use hecmw_util
325 
326  implicit none
327  type (hecmwST_local_mesh) :: hecMESH
328  type (hecmwST_matrix), target :: hecMAT
329  integer(kind=kint) :: METHOD
330  integer(kind=kint) :: ITER, PRECOND, NSET, iterPREmax, NREST,NBFGS
331  integer(kind=kint) :: ITERlog, TIMElog
332 
333  character(len=30) :: msg_precond
334  character(len=30) :: msg_method
335 
336  iter = hecmw_mat_get_iter(hecmat)
337  ! METHOD = hecmw_mat_get_method(hecMAT)
338  precond = hecmw_mat_get_precond(hecmat)
339  nset = hecmw_mat_get_nset(hecmat)
340  iterpremax= hecmw_mat_get_iterpremax(hecmat)
341  nrest = hecmw_mat_get_nrest(hecmat)
342  nbfgs = hecmw_mat_get_nbfgs(hecmat)
343  iterlog= hecmw_mat_get_iterlog(hecmat)
344  timelog= hecmw_mat_get_timelog(hecmat)
345 
346  select case(method)
347  case (1) !--CG
348  msg_method="CG"
349  case (2) !--BiCGSTAB
350  msg_method="BiCGSTAB"
351  case (3) !--GMRES
352  msg_method="GMRES"
353  case (4) !--GPBiCG
354  msg_method="GPBiCG"
355  case (5)
356  if (nbfgs==0) then
357  msg_method="GMRESR"
358  else
359  msg_method="SUP-GMRESR"
360  endif
361  case (6)
362  msg_method="GMRESR-EN"
363  case (7) !--CR
364  msg_method="CR"
365  case (8) !--PipeCG
366  msg_method="PipeCG"
367  case (9) !--GroppCG
368  msg_method="GroppCG"
369  case default
370  msg_method="Unlabeled"
371  end select
372  select case(precond)
373  case (1,2)
374  msg_precond="SSOR"
375  case (3)
376  msg_precond="DIAG"
377  case (5)
378  msg_precond="ML"
379  case (7)
380  msg_precond="DirectMUMPS"
381  case (10, 11, 12)
382  write(msg_precond,"(a,i0,a)") "ILU(",precond-10,")"
383  case (20)
384  msg_precond="SAINV"
385  case (21)
386  msg_precond="RIF"
387  case (22)
388  msg_precond="SAAMG"
389  case default
390  msg_precond="Unlabeled"
391  end select
392  if (hecmesh%my_rank.eq.0 .and. (iterlog.eq.1 .or. timelog.ge.1)) then
393  write (*,'(a,i0,a,i0,a,a,a,a,a,i0)') '### ',hecmat%NDOF,'x',hecmat%NDOF,' BLOCK ', &
394  & trim(msg_method),", ",trim(msg_precond),", ", iterpremax
395  end if
396  end subroutine hecmw_solve_iterative_printmsg
397 
398 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_omega(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_omega(hecMAT, omega)
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)
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