FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
hecmw_solver_BiCGSTAB.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***
8 !C*** module hecmw_solver_BiCGSTAB
9 !C***
10 !C
12 contains
13  !C
14  !C*** BiCGSTAB_3
15  !C
16  subroutine hecmw_solve_bicgstab( hecMESH, hecMAT, ITER, RESID, error, &
17  & Tset, Tsol, Tcomm )
18 
19  use hecmw_util
21  use m_hecmw_comm_f
26  use hecmw_precond
27  use hecmw_jad_type
28 
29  implicit none
30 
31  type(hecmwst_local_mesh) :: hecMESH
32  type(hecmwst_matrix) :: hecMAT
33  integer(kind=kint ), intent(inout):: ITER, error
34  real (kind=kreal), intent(inout):: resid, tset, tsol, tcomm
35 
36  integer(kind=kint ) :: N, NP, NDOF, NNDOF
37  integer(kind=kint ) :: my_rank
38  integer(kind=kint ) :: ITERlog, TIMElog
39  real(kind=kreal), pointer :: b(:), x(:)
40 
41  real(kind=kreal), dimension(:,:), allocatable :: ww
42  real(kind=kreal), dimension(2) :: cg
43 
44  integer(kind=kint ) :: MAXIT
45 
46  ! local variables
47  real (kind=kreal):: tol
48  real (kind=kreal)::s_time,s1_time,e_time,e1_time, start_time, end_time
49  real (kind=kreal)::bnrm2,c2
50  real (kind=kreal)::rho,rho1,beta,alpha,dnrm2
51  real (kind=kreal)::omega
52  real (kind=kreal)::t_max,t_min,t_avg,t_sd
53 
54  integer(kind=kint), parameter :: R = 1
55  integer(kind=kint), parameter :: RT= 2
56  integer(kind=kint), parameter :: P = 3
57  integer(kind=kint), parameter :: PT= 4
58  integer(kind=kint), parameter :: S = 5
59  integer(kind=kint), parameter :: ST= 1
60  integer(kind=kint), parameter :: T = 6
61  integer(kind=kint), parameter :: V = 7
62  integer(kind=kint), parameter :: WK= 8
63 
64  integer(kind=kint) :: N_ITER_RECOMPUTE_R
65  integer(kind=kint), parameter :: N_ITER_RECOMPUTE_R_DEFAULT= 100
66 
67  call hecmw_barrier(hecmesh)
68  s_time= hecmw_wtime()
69 
70  !C===
71  !C +-------+
72  !C | INIT. |
73  !C +-------+
74  !C===
75  n = hecmat%N
76  np = hecmat%NP
77  ndof = hecmat%NDOF
78  nndof = n * ndof
79  my_rank = hecmesh%my_rank
80  x => hecmat%X
81  b => hecmat%B
82 
83  iterlog = hecmw_mat_get_iterlog( hecmat )
84  timelog = hecmw_mat_get_timelog( hecmat )
85  maxit = hecmw_mat_get_iter( hecmat )
86  tol = hecmw_mat_get_resid( hecmat )
87 
88  n_iter_recompute_r = hecmw_mat_get_recompute_residual( hecmat )
89  if (n_iter_recompute_r == 0) n_iter_recompute_r = n_iter_recompute_r_default
90  !C----- negative: never recompute periodically. ITER stops at MAXIT, so mod() below is never 0
91  if (n_iter_recompute_r < 0) n_iter_recompute_r = maxit + 1
92 
93  error = 0
94  rho1 = 0.0d0
95  alpha = 0.0d0
96  beta = 0.0d0
97  omega = 0.0d0
98 
99  allocate (ww(ndof*np, 8))
100  ww = 0.d0
101 
102  !C
103  !C-- SCALING
104  call hecmw_solver_scaling_fw(hecmesh, hecmat, tcomm)
105 
106  !C
107  !C-- matrix integration for OpenACC
108  !C
109  !C @note:
110  !C Combine hecMAT%AL, D, and AU into a single matrix for GPU execution.
111  !C This is a no-op for CPU builds.
112  call hecmw_mat_integrate(hecmat)
113 
114  if (hecmw_mat_get_usejad(hecmat).ne.0) then
115  call hecmw_jad_init(hecmat)
116  endif
117  call hecmw_matvec_setup(hecmesh, hecmat)
118 
119  !C===
120  !C +----------------------+
121  !C | SETUP PRECONDITIONER |
122  !C +----------------------+
123  !C===
124  call hecmw_precond_setup(hecmat, hecmesh, 0)
125 
126  !C===
127  !C +---------------------+
128  !C | {r0}= {b} - [A]{x0} |
129  !C +---------------------+
130  !C===
131  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
132 
133  !C-- set arbitrary {r_tld}
134  call hecmw_copy_r(nndof, ww(:,r), ww(:,rt))
135 
136  !C-- compute ||{b}||
137  call hecmw_innerproduct_r(hecmesh, ndof, b, b, bnrm2, tcomm)
138  if (bnrm2.eq.0.d0) then
139  iter = 0
140  maxit = 0
141  resid = 0.d0
142  x = 0.d0
143  endif
144 
145  e_time = hecmw_wtime()
146  if (timelog.eq.2) then
147  call hecmw_time_statistics(hecmesh, e_time - s_time, &
148  t_max, t_min, t_avg, t_sd)
149  if (hecmesh%my_rank.eq.0) then
150  write(*,*) 'Time solver setup'
151  write(*,*) ' Max :',t_max
152  write(*,*) ' Min :',t_min
153  write(*,*) ' Avg :',t_avg
154  write(*,*) ' Std Dev :',t_sd
155  endif
156  tset = t_max
157  else
158  tset = e_time - s_time
159  endif
160 
161  tcomm = 0.d0
162  call hecmw_barrier(hecmesh)
163  s1_time = hecmw_wtime()
164  !C
165  !C*************************************************************** iterative procedures start
166  !C
167  do iter = 1, maxit
168 
169  !C===
170  !C +-----------------+
171  !C | RHO= {r}{r_tld} |
172  !C +-----------------+
173  !C===
174  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,r), ww(:,rt), rho, tcomm)
175 
176  !C===
177  !C +----------------------------------------+
178  !C | BETA= (RHO/RHO1) * (ALPHA/OMEGA) |
179  !C | {p} = {r} + BETA * ( {p} - OMEGA*{v} ) |
180  !C +----------------------------------------+
181  !C===
182  if ( iter.gt.1 ) then
183  beta = (rho/rho1) * (alpha/omega)
184  call hecmw_axpy_r(nndof, -omega, ww(:,v), ww(:,p))
185  call hecmw_xpay_r(nndof, beta, ww(:,r), ww(:,p))
186  else
187  call hecmw_copy_r(nndof, ww(:,r), ww(:,p))
188  endif
189 
190  !C===
191  !C +--------------------+
192  !C | {p_tld}= [Minv]{p} |
193  !C +--------------------+
194  !C===
195  call hecmw_precond_apply(hecmesh, hecmat, ww(:, p), ww(:, pt), ww(:, wk), tcomm)
196 
197  !C===
198  !C +-------------------------+
199  !C | {v}= [A] {p_tld} |
200  !C +-------------------------+
201  !C===
202  call hecmw_matvec(hecmesh, hecmat, ww(:,pt), ww(:,v), tcomm)
203 
204  !C
205  !C-- calc. ALPHA
206  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,rt), ww(:,v), c2, tcomm)
207 
208  alpha = rho / c2
209 
210  !C
211  !C-- {s}= {r} - ALPHA*{V}
212  call hecmw_axpyz_r(nndof, -alpha, ww(:,v), ww(:,r), ww(:,s))
213 
214  !C===
215  !C +--------------------+
216  !C | {s_tld}= [Minv]{s} |
217  !C +--------------------+
218  !C===
219  call hecmw_precond_apply(hecmesh, hecmat, ww(:, s), ww(:, st), ww(:, wk), tcomm)
220 
221  !C===
222  !C +-------------------------+
223  !C | {t}= [A] {s_tld} |
224  !C +-------------------------+
225  !C===
226  call hecmw_matvec(hecmesh, hecmat, ww(:,st), ww(:,t), tcomm)
227 
228  !C===
229  !C +----------------------------+
230  !C | OMEGA= ({t}{s}) / ({t}{t}) |
231  !C +----------------------------+
232  !C===
233  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,t), ww(:,s), cg(1))
234  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,t), ww(:,t), cg(2))
235  s_time= hecmw_wtime()
236  call hecmw_allreduce_r(hecmesh, cg, 2, hecmw_sum)
237  e_time= hecmw_wtime()
238  tcomm = tcomm + e_time - s_time
239 
240  omega = cg(1) / cg(2)
241 
242  !C===
243  !C +----------------+
244  !C | update {x},{r} |
245  !C +----------------+
246  !C===
247  call hecmw_axpy_r(nndof, alpha, ww(:,pt), x)
248  call hecmw_axpy_r(nndof, omega, ww(:,st), x)
249  !C
250  !C--- recompute R sometimes
251  if ( mod(iter,n_iter_recompute_r)==0 ) then
252  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
253  else
254  call hecmw_axpyz_r(nndof, -omega, ww(:,t), ww(:,s), ww(:,r))
255  endif
256 
257  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,r), ww(:,r), dnrm2, tcomm)
258 
259  resid= dsqrt(dnrm2/bnrm2)
260 
261  !C##### ITERATION HISTORY
262  if (my_rank.eq.0.and.iterlog.eq.1) write (*,'(i7, 1pe16.6)') iter, resid
263  !C#####
264 
265  if ( resid.le.tol ) then
266  if ( mod(iter,n_iter_recompute_r)==0 ) exit
267  !C----- recompute R to make sure it is really converged
268  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
269  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,r), ww(:,r), dnrm2, tcomm)
270  resid= dsqrt(dnrm2/bnrm2)
271  if ( resid.le.tol ) exit
272  endif
273  if ( iter .eq.maxit ) error = hecmw_solver_error_noconv_maxit
274 
275  rho1 = rho
276 
277  enddo
278  !C
279  !C*************************************************************** iterative procedures end
280  !C
281 
282  call hecmw_solver_scaling_bk(hecmat)
283  !C
284  !C-- INTERFACE data EXCHANGE
285  !C
286  start_time = hecmw_wtime()
287  call hecmw_update_r (hecmesh, x, hecmat%NP, hecmat%NDOF)
288  end_time = hecmw_wtime()
289  tcomm = tcomm + end_time - start_time
290 
291  deallocate (ww)
292  !call hecmw_precond_clear(hecMAT)
293 
294  call hecmw_matvec_teardown(hecmat)
295  if (hecmw_mat_get_usejad(hecmat).ne.0) then
296  call hecmw_jad_finalize(hecmat)
297  endif
298 
299  e1_time = hecmw_wtime()
300  if (timelog.eq.2) then
301  call hecmw_time_statistics(hecmesh, e1_time - s1_time, &
302  t_max, t_min, t_avg, t_sd)
303  if (hecmesh%my_rank.eq.0) then
304  write(*,*) 'Time solver iterations'
305  write(*,*) ' Max :',t_max
306  write(*,*) ' Min :',t_min
307  write(*,*) ' Avg :',t_avg
308  write(*,*) ' Std Dev :',t_sd
309  endif
310  tsol = t_max
311  else
312  tsol = e1_time - s1_time
313  endif
314 
315  end subroutine hecmw_solve_bicgstab
316 end module hecmw_solver_bicgstab
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 hecmw_solve_bicgstab(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_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