FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_solver_PipeCG.f90
Go to the documentation of this file.
1 !C
2 !C*** module hecmw_solver_PipeCG
3 !C
5 
6  public :: hecmw_solve_pipecg
7 
8 contains
9  !C
10  !C*** Pipelined CG
11  !C
12  subroutine hecmw_solve_pipecg( hecMESH, hecMAT, ITER, RESID, error, &
13  & Tset, Tsol, Tcomm )
14 
15  use hecmw_util
17  use m_hecmw_comm_f
22  use hecmw_precond
23  use hecmw_jad_type
25 
26  implicit none
27 
28  type(hecmwst_local_mesh) :: hecmesh
29  type(hecmwst_matrix) :: hecmat
30  integer(kind=kint), intent(inout) :: iter, error
31  real(kind=kreal), intent(inout) :: resid, tset, tsol, tcomm
32 
33  integer(kind=kint) :: n, np, ndof, nndof
34  integer(kind=kint) :: my_rank
35  integer(kind=kint) :: iterlog, timelog
36  real(kind=kreal), pointer :: b(:), x(:)
37 
38  real(kind=kreal), dimension(:,:), allocatable :: ww
39 
40  integer(kind=kint), parameter :: r = 1
41  integer(kind=kint), parameter :: u = 2
42  integer(kind=kint), parameter :: v = 3
43  integer(kind=kint), parameter :: q = 4
44  integer(kind=kint), parameter :: p = 5
45  integer(kind=kint), parameter :: z = 6
46  integer(kind=kint), parameter :: l = 7
47  integer(kind=kint), parameter :: m = 8
48  integer(kind=kint), parameter :: s = 9
49  integer(kind=kint), parameter :: wk = 10
50 
51  integer(kind=kint) :: maxit
52 
53  real(kind=kreal) :: tol
54  integer(kind=kint) :: i
55  real(kind=kreal) :: s_time, s1_time, e_time, e1_time
56  real(kind=kreal) :: start_time, end_time
57  real(kind=kreal) :: bnrm2, dnrm2
58  real(kind=kreal) :: alpha, alpha1, beta
59  real(kind=kreal) :: gamma, gamma1, delta, denom
60  real(kind=kreal) :: cg(3)
61  real(kind=kreal) :: t_max, t_min, t_avg, t_sd
62  integer(kind=kint) :: estcond
63  real(kind=kreal), allocatable :: d(:), e(:)
64  integer(kind=kint) :: n_indef_precond
65 
66  integer(kind=kint) :: n_iter_recompute_r
67  integer(kind=kint), parameter :: n_iter_recompute_r_default = 50
68 
69  call hecmw_barrier(hecmesh)
70  s_time = hecmw_wtime()
71 
72  n = hecmat%N
73  np = hecmat%NP
74  ndof = hecmat%NDOF
75  nndof = n * ndof
76  my_rank = hecmesh%my_rank
77  x => hecmat%X
78  b => hecmat%B
79 
80  iterlog = hecmw_mat_get_iterlog(hecmat)
81  timelog = hecmw_mat_get_timelog(hecmat)
82  maxit = hecmw_mat_get_iter(hecmat)
83  tol = hecmw_mat_get_resid(hecmat)
84  estcond = hecmw_mat_get_estcond(hecmat)
85 
86  n_iter_recompute_r = hecmw_mat_get_recompute_residual( hecmat )
87  if (n_iter_recompute_r == 0) n_iter_recompute_r = n_iter_recompute_r_default
88  !C----- negative: never recompute periodically. i stops at MAXIT, so mod() below is never 0
89  if (n_iter_recompute_r < 0) n_iter_recompute_r = maxit + 1
90 
91  error = 0
92  iter = 0
93  n_indef_precond = 0
94  gamma1 = 1.0d0
95  alpha1 = 1.0d0
96 
97  allocate(ww(ndof*np, 10))
98  ww = 0.0d0
99 
100  call hecmw_solver_scaling_fw(hecmesh, hecmat, tcomm)
101  call hecmw_mat_integrate(hecmat)
102 
103  if (hecmw_mat_get_usejad(hecmat).ne.0) then
104  call hecmw_jad_init(hecmat)
105  endif
106 
107  if (estcond /= 0 .and. hecmesh%my_rank == 0) then
108  allocate(d(maxit), e(maxit-1))
109  endif
110 
111  call hecmw_precond_setup(hecmat, hecmesh, 1)
112 
113  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
114  call hecmw_innerproduct_r(hecmesh, ndof, b, b, bnrm2, tcomm)
115  if (bnrm2.eq.0.0d0) then
116  maxit = 0
117  resid = 0.0d0
118  x = 0.0d0
119  else
120  call hecmw_precond_apply(hecmesh, hecmat, ww(:,r), ww(:,u), ww(:,wk), tcomm)
121  call hecmw_matvec(hecmesh, hecmat, ww(:,u), ww(:,v), tcomm)
122  endif
123 
124  e_time = hecmw_wtime()
125  if (timelog.eq.2) then
126  call hecmw_time_statistics(hecmesh, e_time-s_time, t_max, t_min, t_avg, t_sd)
127  if (hecmesh%my_rank.eq.0) then
128  write(*,*) 'Time solver setup'
129  write(*,*) ' Max :', t_max
130  write(*,*) ' Min :', t_min
131  write(*,*) ' Avg :', t_avg
132  write(*,*) ' Std Dev :', t_sd
133  endif
134  tset = t_max
135  else
136  tset = e_time-s_time
137  endif
138 
139  tcomm = 0.0d0
140  call hecmw_barrier(hecmesh)
141  s1_time = hecmw_wtime()
142 
143  do i = 1, maxit
144  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,r), ww(:,u), cg(1))
145  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,v), ww(:,u), cg(2))
146  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,r), ww(:,r), cg(3))
147  start_time = hecmw_wtime()
148  call hecmw_allreduce_r(hecmesh, cg, 3, hecmw_sum)
149  end_time = hecmw_wtime()
150  tcomm = tcomm + end_time-start_time
151 
152  gamma = cg(1)
153  delta = cg(2)
154  dnrm2 = cg(3)
155  resid = dsqrt(dnrm2/bnrm2)
156 
157  if (i.eq.1 .and. resid.le.tol) exit
158 
159  if (i.gt.1) then
160  iter = i-1
161  if (my_rank.eq.0 .and. iterlog.eq.1) write(*,'(i7, 1pe16.6)') iter, resid
162  if (resid.le.tol) then
163  if (mod(iter,n_iter_recompute_r).eq.0) exit
164  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
165  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,r), ww(:,r), dnrm2, tcomm)
166  resid = dsqrt(dnrm2/bnrm2)
167  if (resid.le.tol) exit
168 
169  call hecmw_precond_apply(hecmesh, hecmat, ww(:,r), ww(:,u), ww(:,wk), tcomm)
170  call hecmw_matvec(hecmesh, hecmat, ww(:,u), ww(:,v), tcomm)
171  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,r), ww(:,u), cg(1))
172  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,v), ww(:,u), cg(2))
173  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,r), ww(:,r), cg(3))
174  start_time = hecmw_wtime()
175  call hecmw_allreduce_r(hecmesh, cg, 3, hecmw_sum)
176  end_time = hecmw_wtime()
177  tcomm = tcomm + end_time-start_time
178  gamma = cg(1)
179  delta = cg(2)
180  dnrm2 = cg(3)
181  resid = dsqrt(dnrm2/bnrm2)
182  endif
183  endif
184 
185  if (gamma.eq.0.0d0) exit
186  if (gamma.ne.gamma) then
188  iter = i
189  exit
190  elseif (i.gt.1 .and. gamma*gamma1.le.0.0d0) then
191  n_indef_precond = n_indef_precond + 1
192  if (n_indef_precond.ge.3) then
194  iter = i
195  exit
196  endif
197  endif
198 
199  call hecmw_precond_apply(hecmesh, hecmat, ww(:,v), ww(:,m), ww(:,wk), tcomm)
200  call hecmw_matvec(hecmesh, hecmat, ww(:,m), ww(:,l), tcomm)
201 
202  if (i.gt.1) then
203  beta = gamma/gamma1
204  denom = delta-beta*gamma/alpha1
205  else
206  beta = 0.0d0
207  denom = delta
208  endif
209 
210  if (denom.le.0.0d0) then
212  iter = i
213  exit
214  elseif (denom.ne.denom) then
216  iter = i
217  exit
218  endif
219  alpha = gamma/denom
220 
221  call hecmw_xpay_r(nndof, beta, ww(:,l), ww(:,z))
222  call hecmw_xpay_r(nndof, beta, ww(:,m), ww(:,q))
223  call hecmw_xpay_r(nndof, beta, ww(:,v), ww(:,s))
224  call hecmw_xpay_r(nndof, beta, ww(:,u), ww(:,p))
225 
226  call hecmw_axpy_r(nndof, alpha, ww(:,p), x)
227  if (mod(i,n_iter_recompute_r).eq.0) then
228  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
229  call hecmw_precond_apply(hecmesh, hecmat, ww(:,r), ww(:,u), ww(:,wk), tcomm)
230  call hecmw_matvec(hecmesh, hecmat, ww(:,u), ww(:,v), tcomm)
231  else
232  call hecmw_axpy_r(nndof, -alpha, ww(:,s), ww(:,r))
233  call hecmw_axpy_r(nndof, -alpha, ww(:,q), ww(:,u))
234  call hecmw_axpy_r(nndof, -alpha, ww(:,z), ww(:,v))
235  endif
236 
237  iter = i
238  if (estcond /= 0 .and. hecmesh%my_rank == 0) then
239  if (i.eq.1) then
240  d(1) = 1.0d0/alpha
241  else
242  d(i) = 1.0d0/alpha+beta/alpha1
243  e(i-1) = dsqrt(beta)/alpha1
244  endif
245  if (mod(i,estcond).eq.0) call hecmw_estimate_condition_cg(i, d, e)
246  endif
247 
248  gamma1 = gamma
249  alpha1 = alpha
250 
251  if (i.eq.maxit) then
252  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
253  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,r), ww(:,r), dnrm2, tcomm)
254  resid = dsqrt(dnrm2/bnrm2)
255  if (my_rank.eq.0 .and. iterlog.eq.1) write(*,'(i7, 1pe16.6)') iter, resid
256  if (resid.gt.tol) error = hecmw_solver_error_noconv_maxit
257  endif
258  enddo
259 
260  call hecmw_solver_scaling_bk(hecmat)
261 
262  start_time = hecmw_wtime()
263  call hecmw_update_r(hecmesh, x, hecmat%NP, hecmat%NDOF)
264  end_time = hecmw_wtime()
265  tcomm = tcomm + end_time-start_time
266 
267  deallocate(ww)
268 
269  if (hecmw_mat_get_usejad(hecmat).ne.0) then
270  call hecmw_jad_finalize(hecmat)
271  endif
272 
273  if (estcond /= 0 .and. hecmesh%my_rank == 0) then
274  if (error.eq.0 .and. iter.gt.0) call hecmw_estimate_condition_cg(iter, d, e)
275  deallocate(d, e)
276  endif
277 
278  e1_time = hecmw_wtime()
279  if (timelog.eq.2) then
280  call hecmw_time_statistics(hecmesh, e1_time-s1_time, t_max, t_min, t_avg, t_sd)
281  if (hecmesh%my_rank.eq.0) then
282  write(*,*) 'Time solver iterations'
283  write(*,*) ' Max :', t_max
284  write(*,*) ' Min :', t_min
285  write(*,*) ' Avg :', t_avg
286  write(*,*) ' Std Dev :', t_sd
287  endif
288  tsol = t_max
289  else
290  tsol = e1_time-s1_time
291  endif
292 
293  end subroutine hecmw_solve_pipecg
294 
295 end module hecmw_solver_PipeCG
subroutine, public hecmw_estimate_condition_cg(ITER, D, E)
Jagged Diagonal Matrix storage for vector processors. Original code was provided by JAMSTEC.
Definition: hecmw_jadm.f90:8
subroutine, public hecmw_jad_init(hecMAT)
Definition: hecmw_jadm.f90:29
subroutine, public hecmw_jad_finalize(hecMAT)
Definition: hecmw_jadm.f90:42
subroutine, public hecmw_mat_integrate(hecMAT)
Integrate matrix components into a single array for efficient access.
real(kind=kreal) function, public hecmw_mat_get_resid(hecMAT)
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_recompute_residual(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_estcond(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_usejad(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_iter(hecMAT)
subroutine, public hecmw_precond_setup(hecMAT, hecMESH, sym)
subroutine, public hecmw_precond_apply(hecMESH, hecMAT, R, Z, ZP, COMMtime)
subroutine, public hecmw_matresid(hecMESH, hecMAT, X, B, R, COMMtime)
subroutine, public hecmw_matvec(hecMESH, hecMAT, X, Y, COMMtime)
subroutine hecmw_xpay_r(n, alpha, X, Y)
subroutine hecmw_innerproduct_r_nocomm(hecMESH, ndof, X, Y, sum)
subroutine hecmw_innerproduct_r(hecMESH, ndof, X, Y, sum, COMMtime)
subroutine hecmw_axpy_r(n, alpha, X, Y)
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)
subroutine, public hecmw_solver_scaling_fw(hecMESH, hecMAT, COMMtime)
subroutine, public hecmw_solver_scaling_bk(hecMAT)
I/O and Utility.
Definition: hecmw_util_f.F90:7
integer(kind=kint), parameter hecmw_sum
integer(kind=4), parameter kreal
real(kind=kreal) function hecmw_wtime()
subroutine hecmw_update_r(hecMESH, val, n, m)
subroutine hecmw_allreduce_r(hecMESH, val, n, ntag)
subroutine hecmw_barrier(hecMESH)
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_noconv_maxit
integer(kind=kint), parameter hecmw_solver_error_diverge_mat