FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_solver_GPBiCG.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 
6 !C***
7 !C*** module hecmw_solver_GPBiCG
8 !C***
9 !
11 
12  private
13  public :: hecmw_solve_gpbicg
14 
15 contains
16  !C
17  !C*** hecmw_solve_GPBiCG
18  !C
19  subroutine hecmw_solve_gpbicg( hecMESH, hecMAT, ITER, RESID, error, &
20  & Tset, Tsol, Tcomm )
21  use hecmw_util
23  use m_hecmw_comm_f
28  use hecmw_precond
29  use hecmw_jad_type
30 
31  implicit none
32 
33  type(hecmwst_local_mesh) :: hecmesh
34  type(hecmwst_matrix) :: hecmat
35  integer(kind=kint ), intent(inout):: iter, error
36  real (kind=kreal), intent(inout):: resid, tset, tsol, tcomm
37 
38  integer(kind=kint ) :: n, np, ndof, nndof
39  integer(kind=kint ) :: my_rank
40 
41  real (kind=kreal), pointer :: b(:)
42  real (kind=kreal), pointer :: x(:)
43 
44  integer(kind=kint ) :: iterlog, timelog
45 
46  real(kind=kreal), dimension(:,:), allocatable :: ww
47 
48  real(kind=kreal), dimension(2) :: rr
49 
50  integer(kind=kint ) :: maxit
51  real (kind=kreal) :: tol
52  integer(kind=kint ) :: i,j
53  real (kind=kreal) :: s_time,s1_time,e_time,e1_time
54  real (kind=kreal) :: bnrm2
55  real (kind=kreal) :: rho,rho1,beta,alpha,dnrm2
56  real (kind=kreal) :: qsi,eta,coef1
57  real (kind=kreal) :: t_max,t_min,t_avg,t_sd
58 
59  integer(kind=kint), parameter :: r= 1
60  integer(kind=kint), parameter ::rt= 2
61  integer(kind=kint), parameter :: t= 3
62  integer(kind=kint), parameter ::tt= 4
63  integer(kind=kint), parameter ::t0= 5
64  integer(kind=kint), parameter :: p= 6
65  integer(kind=kint), parameter ::pt= 7
66  integer(kind=kint), parameter :: u= 8
67  integer(kind=kint), parameter ::w1= 9
68  integer(kind=kint), parameter :: y=10
69  integer(kind=kint), parameter :: z=11
70  integer(kind=kint), parameter ::wk=12
71  integer(kind=kint), parameter ::w2=13
72  integer(kind=kint), parameter ::zq=14
73 
74  integer(kind=kint) :: n_iter_recompute_r
75  integer(kind=kint), parameter :: n_iter_recompute_r_default= 20
76 
77  call hecmw_barrier(hecmesh)
78  s_time= hecmw_wtime()
79  !C
80  !C-- INIT.
81  n = hecmat%N
82  np = hecmat%NP
83  ndof = hecmat%NDOF
84  nndof = n * ndof
85  my_rank = hecmesh%my_rank
86  x => hecmat%X
87  b => hecmat%B
88 
89  iterlog = hecmw_mat_get_iterlog( hecmat )
90  timelog = hecmw_mat_get_timelog( hecmat )
91  maxit = hecmw_mat_get_iter( hecmat )
92  tol = hecmw_mat_get_resid( hecmat )
93 
94  n_iter_recompute_r = hecmw_mat_get_recompute_residual( hecmat )
95  if (n_iter_recompute_r == 0) n_iter_recompute_r = n_iter_recompute_r_default
96  !C----- negative: never recompute periodically. ITER stops at MAXIT, so mod() below is never 0
97  if (n_iter_recompute_r < 0) n_iter_recompute_r = maxit + 1
98 
99  error= 0
100  beta = 0.0d0
101 
102  allocate (ww(ndof*np,14))
103  ww= 0.d0
104 
105  !C
106  !C-- SCALING
107  call hecmw_solver_scaling_fw(hecmesh, hecmat, tcomm)
108 
109  !C
110  !C-- matrix integration for OpenACC
111  !C
112  !C @note:
113  !C Combine hecMAT%AL, D, and AU into a single matrix for GPU execution.
114  !C This is a no-op for CPU builds.
115  call hecmw_mat_integrate(hecmat)
116 
117  if (hecmw_mat_get_usejad(hecmat).ne.0) then
118  call hecmw_jad_init(hecmat)
119  endif
120  call hecmw_matvec_setup(hecmesh, hecmat)
121 
122  !C===
123  !C +----------------------+
124  !C | SETUP PRECONDITIONER |
125  !C +----------------------+
126  !C===
127  call hecmw_precond_setup(hecmat, hecmesh, 0)
128 
129  !C
130  !C +----------------------+
131  !C | {r}= {b} - [A]{xini} |
132  !C +----------------------+
133  !C===
134  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
135 
136  call hecmw_copy_r(nndof, ww(:,r), ww(:,rt))
137  !C==
138  call hecmw_innerproduct_r(hecmesh, ndof, b, b, bnrm2, tcomm)
139  if (bnrm2.eq.0.d0) then
140  iter = 0
141  maxit = 0
142  resid = 0.d0
143  x = 0.d0
144  endif
145 
146  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,rt), ww(:,r), rho, tcomm)
147 
148  e_time= hecmw_wtime()
149  if (timelog.eq.2) then
150  call hecmw_time_statistics(hecmesh, e_time - s_time, &
151  t_max, t_min, t_avg, t_sd)
152  if (hecmesh%my_rank.eq.0) then
153  write(*,*) 'Time solver setup'
154  write(*,*) ' Max :',t_max
155  write(*,*) ' Min :',t_min
156  write(*,*) ' Avg :',t_avg
157  write(*,*) ' Std Dev :',t_sd
158  endif
159  tset = t_max
160  else
161  tset = e_time - s_time
162  endif
163  !C===
164 
165  !C
166  !C*************************************************************** ITERATIVE PROC.
167  !C
168  call hecmw_barrier(hecmesh)
169  s1_time= hecmw_wtime()
170  do iter= 1, maxit
171  !C
172  !C +----------------+
173  !C | {r}= [Minv]{r} |
174  !C +----------------+
175  !C===
176  call hecmw_copy_r(nndof, ww(:,r), ww(:,wk))
177 
178  call hecmw_precond_apply(hecmesh, hecmat, ww(:,wk), ww(:,r), ww(:,zq), tcomm)
179  !C===
180 
181  !C
182  !C +----------------------------------+
183  !C | {p} = {r} + BETA * ( {p} - {u} ) |
184  !C +----------------------------------+
185  !C===
186  if (iter.gt.1) then
187  call hecmw_axpy_r(nndof, -1.0d0, ww(:,u), ww(:,p))
188  call hecmw_xpay_r(nndof, beta, ww(:,r), ww(:,p))
189  else
190  call hecmw_copy_r(nndof, ww(:,r), ww(:,p))
191  endif
192  !C===
193 
194  !C
195  !C +--------------------------------+
196  !C | ALPHA= {r_tld}{r}/{r_tld} A{p} |
197  !C +--------------------------------+
198  !C===
199 
200  !C
201  !C-- calc. {p_tld}= A{p}
202  call hecmw_matvec(hecmesh, hecmat, ww(:,p), ww(:,pt), tcomm)
203 
204  !C
205  !C-- calc. ALPHA
206  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,rt), ww(:,pt), rho1, tcomm)
207 
208  alpha= rho / rho1
209  !C===
210 
211  !C
212  !C +------------------------------------------+
213  !C | {y}= {t} - {r} - ALPHA{w} + ALPHA{p_tld} |
214  !C | {t}= {r} - ALPHA{p_tld} |
215  !C +------------------------------------------+
216  !C===
217  call hecmw_axpyz_r(nndof, -1.0d0, ww(:,w1), ww(:,pt), ww(:,y))
218  call hecmw_xpay_r (nndof, alpha, ww(:, t), ww(:, y))
219  call hecmw_axpy_r (nndof, -1.0d0, ww(:,wk), ww(:, y))
220  call hecmw_axpyz_r(nndof, -alpha, ww(:,pt), ww(:,wk), ww(:,t))
221  !C===
222 
223  !C
224  !C +-----------------------+
225  !C | {t_tld}= [A][Minv]{t} |
226  !C +-----------------------+
227  !C===
228 
229  !C
230  !C-- calc. {t_tld} and {t0} by [M] inversion
231  !C {W2} = [Minv]{p_tld}
232  !C
233  call hecmw_precond_apply(hecmesh, hecmat, ww(:,t), ww(:,tt), ww(:,zq), tcomm)
234  call hecmw_precond_apply(hecmesh, hecmat, ww(:,t0), ww(:,w2), ww(:,zq), tcomm)
235  call hecmw_copy_r(nndof, ww(:,w2), ww(:,t0))
236  call hecmw_precond_apply(hecmesh, hecmat, ww(:,pt), ww(:,w2), ww(:,zq), tcomm)
237 
238  !C===
239 
240  !C
241  !C-- calc. [A]{t_tld}
242  call hecmw_matvec(hecmesh, hecmat, ww(:,tt), ww(:,wk), tcomm)
243 
244  call hecmw_copy_r(nndof, ww(:,wk), ww(:,tt))
245  !C===
246 
247  !C
248  !C +-------------------+
249  !C | calc. QSI and ETA |
250  !C +-------------------+
251  !C===
252  call pol_coef_vanilla2(iter, ww, t, tt, y, qsi, eta)
253  !C===
254 
255  !C
256  !C +----------------------------------------------------------+
257  !C | {u} = QSI [Minv]{pt} + ETA([Minv]{t0}-[Minv]{r}+BETA*{u} |
258  !C | {z} = QSI [Minv]{r} + ETA*{z} - ALPHA*{u} |
259  !C +----------------------------------------------------------+
260  !C===
261 
262  !C
263  !C-- compute. {u},{z}
264 
265  if (iter.gt.1) then
266  call hecmw_xpay_r (nndof, beta, ww(:,t0), ww(:,u))
267  call hecmw_axpy_r (nndof, -1.0d0, ww(:, r), ww(:,u))
268  call hecmw_axpby_r(nndof, qsi, eta, ww(:,w2), ww(:,u))
269  call hecmw_axpby_r(nndof, -alpha, eta, ww(:, u), ww(:,z))
270  call hecmw_axpy_r (nndof, qsi, ww(:,r), ww(:,z))
271  else
272  call hecmw_axpyz_r(nndof, -1.0d0, ww(:,r), ww(:,t0), ww(:,u))
273  call hecmw_axpby_r(nndof, qsi, eta, ww(:,w2), ww(:,u))
274  call hecmw_axpby_r(nndof, -alpha, eta, ww(:, u), ww(:,z))
275  call hecmw_axpy_r (nndof, qsi, ww(:,r), ww(:,z))
276  endif
277  !C===
278 
279  !C
280  !C +--------------------+
281  !C | update {x},{r},{w} |
282  !C +--------------------+
283  !C===
284  call hecmw_axpy_r(nndof, alpha, ww(:,p), x)
285  call hecmw_axpy_r(nndof, 1.0d0, ww(:,z), x)
286  call hecmw_copy_r(nndof, ww(:,t), ww(:,t0))
287  !C
288  !C--- recompute R sometimes
289  if ( mod(iter,n_iter_recompute_r)==0 ) then
290  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
291  else
292  call hecmw_axpyz_r(nndof, -eta, ww(:,y), ww(:,t), ww(:,r))
293  call hecmw_axpy_r (nndof, -qsi, ww(:,tt), ww(:,r))
294  endif
295 
296  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,r), ww(:,r), rr(1))
297  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,r), ww(:,rt), rr(2))
298  s_time= hecmw_wtime()
299  call hecmw_allreduce_r(hecmesh, rr, 2, hecmw_sum)
300  e_time= hecmw_wtime()
301  tcomm = tcomm + e_time - s_time
302  dnrm2 = rr(1)
303  coef1 = rr(2)
304 
305  beta = alpha*coef1 / (qsi*rho)
306  call hecmw_axpyz_r(nndof, beta, ww(:,pt), ww(:,tt), ww(:,w1))
307 
308  resid= dsqrt(dnrm2/bnrm2)
309  rho = coef1
310 
311  !C##### ITERATION HISTORY
312  if (my_rank.eq.0 .and. iterlog.eq.1) &
313  & write (*, 1000) iter, resid
314  1000 format (i5, 1pe16.6)
315  !C#####
316 
317  if (resid.le.tol ) then
318  if ( mod(iter,n_iter_recompute_r)==0 ) exit
319  !C----- recompute R to make sure it is really converged
320  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
321  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,r), ww(:,r), dnrm2, tcomm)
322  resid= dsqrt(dnrm2/bnrm2)
323  if (resid.le.tol) exit
324  endif
325  if ( iter.eq.maxit ) error= hecmw_solver_error_noconv_maxit
326  !C===
327  enddo
328 
329  call hecmw_solver_scaling_bk(hecmat)
330  !C
331  !C-- INTERFACE data EXCHANGE
332 
333  s_time = hecmw_wtime()
334  call hecmw_update_r (hecmesh, x, hecmat%NP, hecmat%NDOF)
335  e_time = hecmw_wtime()
336  tcomm = tcomm + e_time - s_time
337 
338  deallocate (ww)
339  !call hecmw_precond_clear(hecMAT)
340 
341  call hecmw_matvec_teardown(hecmat)
342  if (hecmw_mat_get_usejad(hecmat).ne.0) then
343  call hecmw_jad_finalize(hecmat)
344  endif
345 
346  e1_time= hecmw_wtime()
347  if (timelog.eq.2) then
348  call hecmw_time_statistics(hecmesh, e1_time - s1_time, &
349  t_max, t_min, t_avg, t_sd)
350  if (hecmesh%my_rank.eq.0) then
351  write(*,*) 'Time solver iterations'
352  write(*,*) ' Max :',t_max
353  write(*,*) ' Min :',t_min
354  write(*,*) ' Avg :',t_avg
355  write(*,*) ' Std Dev :',t_sd
356  endif
357  tsol = t_max
358  else
359  tsol = e1_time - s1_time
360  endif
361 
362  contains
363 
364  !C
365  !C*** pol_coef_vanilla2 : computes QSI and ETA with optimized strategy
366  !C
367  subroutine pol_coef_vanilla2(iter, WW, T, TT, Y, QSI, ETA)
368  implicit none
369  integer(kind=kint), intent(in) :: iter
370  real(kind=kreal), intent(inout) :: ww(:,:)
371  integer(kind=kint), intent(in) :: T, TT, Y
372  real(kind=kreal), intent(out) :: qsi, eta
373 
374  real(kind=kreal), dimension(6) :: cg
375  real(kind=kreal) :: gamma1, gamma2
376  real(kind=kreal) :: c, c_abs
377 
378  real(kind=kreal), parameter :: omega = 0.707106781d0
379 
380  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,t ), ww(:,t ), cg(1)) ! |r|^2
381  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,tt), ww(:,tt), cg(2)) ! |s|^2
382  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,t ), ww(:,tt), cg(3)) ! r.s
383 
384  if (iter.gt.1) then
385  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,y ), cg(4)) ! myu
386  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,tt), cg(5)) ! nyu
387  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,t ), cg(6)) ! omega
388  s_time= hecmw_wtime()
389  call hecmw_allreduce_r(hecmesh, cg, 6, hecmw_sum)
390  e_time= hecmw_wtime()
391  tcomm = tcomm + e_time - s_time
392  gamma1 = cg(6)/cg(4) ! omega / myu
393  gamma2 = cg(5)/cg(4) ! nyu / myu
394  else
395  s_time= hecmw_wtime()
396  call hecmw_allreduce_r(hecmesh, cg, 3, hecmw_sum)
397  e_time= hecmw_wtime()
398  tcomm = tcomm + e_time - s_time
399  gamma1 = 0.d0
400  gamma2 = 0.d0
401  endif
402 
403  c = cg(3) / dsqrt(cg(1)*cg(2))
404  c_abs = dabs(c)
405  if (c_abs > omega) then
406  qsi = c * dsqrt(cg(1)/cg(2))
407  else
408  if (c >= 0.d0) then
409  qsi = omega * dsqrt(cg(1)/cg(2))
410  else
411  qsi = -omega * dsqrt(cg(1)/cg(2))
412  endif
413  endif
414  eta = gamma1 - qsi*gamma2
415  end subroutine pol_coef_vanilla2
416 
417  end subroutine hecmw_solve_gpbicg
418 
419 end module hecmw_solver_gpbicg
subroutine pol_coef_vanilla2(iter, WW, T, TT, Y, QSI, ETA)
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_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_solve_gpbicg(hecMESH, hecMAT, ITER, RESID, error, Tset, Tsol, Tcomm)
subroutine, public hecmw_matvec_teardown(hecMAT)
subroutine, public hecmw_matvec_setup(hecMESH, hecMAT)
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_axpyz_r(n, alpha, X, Y, Z)
subroutine hecmw_innerproduct_r_nocomm(hecMESH, ndof, X, Y, sum)
subroutine hecmw_innerproduct_r(hecMESH, ndof, X, Y, sum, COMMtime)
subroutine hecmw_axpby_r(n, alpha, beta, X, Y)
subroutine hecmw_axpy_r(n, alpha, X, Y)
subroutine hecmw_copy_r(n, X, Y)
subroutine hecmw_time_statistics(hecMESH, time, t_max, t_min, t_avg, t_sd)
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_noconv_maxit