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