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 
30  implicit none
31 
32  type(hecmwst_local_mesh) :: hecmesh
33  type(hecmwst_matrix) :: hecmat
34  integer(kind=kint ), intent(inout):: iter, error
35  real (kind=kreal), intent(inout):: resid, tset, tsol, tcomm
36 
37  integer(kind=kint ) :: n, np, ndof, nndof
38  integer(kind=kint ) :: my_rank
39 
40  real (kind=kreal), pointer :: b(:)
41  real (kind=kreal), pointer :: x(:)
42 
43  integer(kind=kint ) :: iterlog, timelog
44 
45  real(kind=kreal), dimension(:,:), allocatable :: ww
46 
47  real(kind=kreal), dimension(2) :: rr
48 
49  integer(kind=kint ) :: maxit
50  real (kind=kreal) :: tol
51  integer(kind=kint ) :: i,j
52  real (kind=kreal) :: s_time,s1_time,e_time,e1_time
53  real (kind=kreal) :: bnrm2
54  real (kind=kreal) :: rho,rho1,beta,alpha,dnrm2
55  real (kind=kreal) :: qsi,eta,coef1
56  real (kind=kreal) :: t_max,t_min,t_avg,t_sd
57 
58  integer(kind=kint), parameter :: r= 1
59  integer(kind=kint), parameter ::rt= 2
60  integer(kind=kint), parameter :: t= 3
61  integer(kind=kint), parameter ::tt= 4
62  integer(kind=kint), parameter ::t0= 5
63  integer(kind=kint), parameter :: p= 6
64  integer(kind=kint), parameter ::pt= 7
65  integer(kind=kint), parameter :: u= 8
66  integer(kind=kint), parameter ::w1= 9
67  integer(kind=kint), parameter :: y=10
68  integer(kind=kint), parameter :: z=11
69  integer(kind=kint), parameter ::wk=12
70  integer(kind=kint), parameter ::w2=13
71  integer(kind=kint), parameter ::zq=14
72 
73  integer(kind=kint), parameter :: n_iter_recompute_r= 20
74 
75  call hecmw_barrier(hecmesh)
76  s_time= hecmw_wtime()
77  !C
78  !C-- INIT.
79  n = hecmat%N
80  np = hecmat%NP
81  ndof = hecmat%NDOF
82  nndof = n * ndof
83  my_rank = hecmesh%my_rank
84  x => hecmat%X
85  b => hecmat%B
86 
87  iterlog = hecmw_mat_get_iterlog( hecmat )
88  timelog = hecmw_mat_get_timelog( hecmat )
89  maxit = hecmw_mat_get_iter( hecmat )
90  tol = hecmw_mat_get_resid( hecmat )
91 
92  error= 0
93  beta = 0.0d0
94 
95  allocate (ww(ndof*np,14))
96  ww= 0.d0
97 
98  !C
99  !C-- SCALING
100  call hecmw_solver_scaling_fw(hecmesh, hecmat, tcomm)
101 
102  !C
103  !C-- matrix integration for OpenACC
104  !C
105  !C @note:
106  !C Combine hecMAT%AL, D, and AU into a single matrix for GPU execution.
107  !C This is a no-op for CPU builds.
108  call hecmw_mat_integrate(hecmat)
109 
110  !C===
111  !C +----------------------+
112  !C | SETUP PRECONDITIONER |
113  !C +----------------------+
114  !C===
115  call hecmw_precond_setup(hecmat, hecmesh, 0)
116 
117  !C
118  !C +----------------------+
119  !C | {r}= {b} - [A]{xini} |
120  !C +----------------------+
121  !C===
122  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
123 
124  call hecmw_copy_r(nndof, ww(:,r), ww(:,rt))
125  !C==
126  call hecmw_innerproduct_r(hecmesh, ndof, b, b, bnrm2, tcomm)
127  if (bnrm2.eq.0.d0) then
128  iter = 0
129  maxit = 0
130  resid = 0.d0
131  x = 0.d0
132  endif
133 
134  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,rt), ww(:,r), rho, tcomm)
135 
136  e_time= hecmw_wtime()
137  if (timelog.eq.2) then
138  call hecmw_time_statistics(hecmesh, e_time - s_time, &
139  t_max, t_min, t_avg, t_sd)
140  if (hecmesh%my_rank.eq.0) then
141  write(*,*) 'Time solver setup'
142  write(*,*) ' Max :',t_max
143  write(*,*) ' Min :',t_min
144  write(*,*) ' Avg :',t_avg
145  write(*,*) ' Std Dev :',t_sd
146  endif
147  tset = t_max
148  else
149  tset = e_time - s_time
150  endif
151  !C===
152 
153  !C
154  !C*************************************************************** ITERATIVE PROC.
155  !C
156  call hecmw_barrier(hecmesh)
157  s1_time= hecmw_wtime()
158  do iter= 1, maxit
159  !C
160  !C +----------------+
161  !C | {r}= [Minv]{r} |
162  !C +----------------+
163  !C===
164  call hecmw_copy_r(nndof, ww(:,r), ww(:,wk))
165 
166  call hecmw_precond_apply(hecmesh, hecmat, ww(:,wk), ww(:,r), ww(:,zq), tcomm)
167  !C===
168 
169  !C
170  !C +----------------------------------+
171  !C | {p} = {r} + BETA * ( {p} - {u} ) |
172  !C +----------------------------------+
173  !C===
174  if (iter.gt.1) then
175  call hecmw_axpy_r(nndof, -1.0d0, ww(:,u), ww(:,p))
176  call hecmw_xpay_r(nndof, beta, ww(:,r), ww(:,p))
177  else
178  call hecmw_copy_r(nndof, ww(:,r), ww(:,p))
179  endif
180  !C===
181 
182  !C
183  !C +--------------------------------+
184  !C | ALPHA= {r_tld}{r}/{r_tld} A{p} |
185  !C +--------------------------------+
186  !C===
187 
188  !C
189  !C-- calc. {p_tld}= A{p}
190  call hecmw_matvec(hecmesh, hecmat, ww(:,p), ww(:,pt), tcomm)
191 
192  !C
193  !C-- calc. ALPHA
194  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,rt), ww(:,pt), rho1, tcomm)
195 
196  alpha= rho / rho1
197  !C===
198 
199  !C
200  !C +------------------------------------------+
201  !C | {y}= {t} - {r} - ALPHA{w} + ALPHA{p_tld} |
202  !C | {t}= {r} - ALPHA{p_tld} |
203  !C +------------------------------------------+
204  !C===
205  call hecmw_axpyz_r(nndof, -1.0d0, ww(:,w1), ww(:,pt), ww(:,y))
206  call hecmw_xpay_r (nndof, alpha, ww(:, t), ww(:, y))
207  call hecmw_axpy_r (nndof, -1.0d0, ww(:,wk), ww(:, y))
208  call hecmw_axpyz_r(nndof, -alpha, ww(:,pt), ww(:,wk), ww(:,t))
209  !C===
210 
211  !C
212  !C +-----------------------+
213  !C | {t_tld}= [A][Minv]{t} |
214  !C +-----------------------+
215  !C===
216 
217  !C
218  !C-- calc. {t_tld} and {t0} by [M] inversion
219  !C {W2} = [Minv]{p_tld}
220  !C
221  call hecmw_precond_apply(hecmesh, hecmat, ww(:,t), ww(:,tt), ww(:,zq), tcomm)
222  call hecmw_precond_apply(hecmesh, hecmat, ww(:,t0), ww(:,w2), ww(:,zq), tcomm)
223  call hecmw_copy_r(nndof, ww(:,w2), ww(:,t0))
224  call hecmw_precond_apply(hecmesh, hecmat, ww(:,pt), ww(:,w2), ww(:,zq), tcomm)
225 
226  !C===
227 
228  !C
229  !C-- calc. [A]{t_tld}
230  call hecmw_matvec(hecmesh, hecmat, ww(:,tt), ww(:,wk), tcomm)
231 
232  call hecmw_copy_r(nndof, ww(:,wk), ww(:,tt))
233  !C===
234 
235  !C
236  !C +-------------------+
237  !C | calc. QSI and ETA |
238  !C +-------------------+
239  !C===
240  !call pol_coef(iter, WW, T, TT, Y, QSI, ETA)
241  !call pol_coef_vanilla(iter, WW, T, TT, Y, QSI, ETA)
242  call pol_coef_vanilla2(iter, ww, t, tt, y, qsi, eta)
243  !C===
244 
245  !C
246  !C +----------------------------------------------------------+
247  !C | {u} = QSI [Minv]{pt} + ETA([Minv]{t0}-[Minv]{r}+BETA*{u} |
248  !C | {z} = QSI [Minv]{r} + ETA*{z} - ALPHA*{u} |
249  !C +----------------------------------------------------------+
250  !C===
251 
252  !C
253  !C-- compute. {u},{z}
254 
255  if (iter.gt.1) then
256  call hecmw_xpay_r (nndof, beta, ww(:,t0), ww(:,u))
257  call hecmw_axpy_r (nndof, -1.0d0, ww(:, r), ww(:,u))
258  call hecmw_axpby_r(nndof, qsi, eta, ww(:,w2), ww(:,u))
259  call hecmw_axpby_r(nndof, -alpha, eta, ww(:, u), ww(:,z))
260  call hecmw_axpy_r (nndof, qsi, ww(:,r), ww(:,z))
261  else
262  call hecmw_axpyz_r(nndof, -1.0d0, ww(:,r), ww(:,t0), ww(:,u))
263  call hecmw_axpby_r(nndof, qsi, eta, ww(:,w2), ww(:,u))
264  call hecmw_axpby_r(nndof, -alpha, eta, ww(:, u), ww(:,z))
265  call hecmw_axpy_r (nndof, qsi, ww(:,r), ww(:,z))
266  endif
267  !C===
268 
269  !C
270  !C +--------------------+
271  !C | update {x},{r},{w} |
272  !C +--------------------+
273  !C===
274  call hecmw_axpy_r(nndof, alpha, ww(:,p), x)
275  call hecmw_axpy_r(nndof, 1.0d0, ww(:,z), x)
276  call hecmw_copy_r(nndof, ww(:,t), ww(:,t0))
277  !C
278  !C--- recompute R sometimes
279  if ( mod(iter,n_iter_recompute_r)==0 ) then
280  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
281  else
282  call hecmw_axpyz_r(nndof, -eta, ww(:,y), ww(:,t), ww(:,r))
283  call hecmw_axpy_r (nndof, -qsi, ww(:,tt), ww(:,r))
284  endif
285 
286  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,r), ww(:,r), rr(1))
287  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,r), ww(:,rt), rr(2))
288  s_time= hecmw_wtime()
289  call hecmw_allreduce_r(hecmesh, rr, 2, hecmw_sum)
290  e_time= hecmw_wtime()
291  tcomm = tcomm + e_time - s_time
292  dnrm2 = rr(1)
293  coef1 = rr(2)
294 
295  beta = alpha*coef1 / (qsi*rho)
296  call hecmw_axpyz_r(nndof, beta, ww(:,pt), ww(:,tt), ww(:,w1))
297 
298  resid= dsqrt(dnrm2/bnrm2)
299  rho = coef1
300 
301  !C##### ITERATION HISTORY
302  if (my_rank.eq.0 .and. iterlog.eq.1) &
303  & write (*, 1000) iter, resid
304  1000 format (i5, 1pe16.6)
305  !C#####
306 
307  if (resid.le.tol ) then
308  if ( mod(iter,n_iter_recompute_r)==0 ) exit
309  !C----- recompute R to make sure it is really converged
310  call hecmw_matresid(hecmesh, hecmat, x, b, ww(:,r), tcomm)
311  call hecmw_innerproduct_r(hecmesh, ndof, ww(:,r), ww(:,r), dnrm2, tcomm)
312  resid= dsqrt(dnrm2/bnrm2)
313  if (resid.le.tol) exit
314  endif
315  if ( iter.eq.maxit ) error= hecmw_solver_error_noconv_maxit
316  !C===
317  enddo
318 
319  call hecmw_solver_scaling_bk(hecmat)
320  !C
321  !C-- INTERFACE data EXCHANGE
322 
323  s_time = hecmw_wtime()
324  call hecmw_update_r (hecmesh, x, hecmat%NP, hecmat%NDOF)
325  e_time = hecmw_wtime()
326  tcomm = tcomm + e_time - s_time
327 
328  deallocate (ww)
329  !call hecmw_precond_clear(hecMAT)
330 
331  e1_time= hecmw_wtime()
332  if (timelog.eq.2) then
333  call hecmw_time_statistics(hecmesh, e1_time - s1_time, &
334  t_max, t_min, t_avg, t_sd)
335  if (hecmesh%my_rank.eq.0) then
336  write(*,*) 'Time solver iterations'
337  write(*,*) ' Max :',t_max
338  write(*,*) ' Min :',t_min
339  write(*,*) ' Avg :',t_avg
340  write(*,*) ' Std Dev :',t_sd
341  endif
342  tsol = t_max
343  else
344  tsol = e1_time - s1_time
345  endif
346 
347  contains
348 
349  !C
350  !C*** pol_coef : computes QSI and ETA in original GPBiCG way
351  !C
352  subroutine pol_coef(iter, WW, T, TT, Y, QSI, ETA)
353  implicit none
354  integer(kind=kint), intent(in) :: iter
355  real(kind=kreal), intent(in) :: ww(:,:)
356  integer(kind=kint), intent(in) :: T, TT, Y
357  real(kind=kreal), intent(out) :: qsi, eta
358 
359  real(kind=kreal), dimension(5) :: cg
360  real(kind=kreal), dimension(2) :: eq
361  real(kind=kreal) :: delta
362 
363  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,y ), cg(1)) ! myu1
364  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,tt), ww(:,t ), cg(2)) ! omega2
365  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,t ), cg(3)) ! omega1
366  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,tt), ww(:,y ), cg(4)) ! nyu
367  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,tt), ww(:,tt), cg(5)) ! myu2
368  s_time= hecmw_wtime()
369  call hecmw_allreduce_r(hecmesh, cg, 5, hecmw_sum)
370  e_time= hecmw_wtime()
371  tcomm = tcomm + e_time - s_time
372 
373  if (iter.eq.1) then
374  eq(1)= cg(2)/cg(5) ! omega2 / myu2
375  eq(2)= 0.d0
376  else
377  delta= (cg(5)*cg(1)-cg(4)*cg(4)) ! myu1*myu2 - nyu^2
378  eq(1)= (cg(1)*cg(2)-cg(3)*cg(4)) / delta ! (myu1*omega2-nyu*omega1)/delta
379  eq(2)= (cg(5)*cg(3)-cg(4)*cg(2)) / delta ! (myu2*omega1-nyu*omega2)/delta
380  endif
381 
382  qsi= eq(1)
383  eta= eq(2)
384  end subroutine pol_coef
385 
386  !C
387  !C*** pol_coef_vanilla : computes QSI and ETA with vanilla strategy
388  !C see Fujino, Abe, Sugihara and Nakashima(2013) ISBN978-4-621-08741-1
389  !C
390  subroutine pol_coef_vanilla(iter, WW, T, TT, Y, QSI, ETA)
391  implicit none
392  integer(kind=kint), intent(in) :: iter
393  real(kind=kreal), intent(inout) :: ww(:,:)
394  integer(kind=kint), intent(in) :: T, TT, Y
395  real(kind=kreal), intent(out) :: qsi, eta
396 
397  real(kind=kreal), dimension(3) :: cg
398  real(kind=kreal) :: gamma1, gamma2
399  real(kind=kreal) :: c, c_abs
400 
401  real(kind=kreal), parameter :: omega = 0.707106781d0
402 
403  if (iter.eq.1) then
404  gamma1 = 0.d0
405  gamma2 = 0.d0
406  else
407  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,y ), cg(1)) ! myu
408  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,tt), cg(2)) ! nyu
409  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,t ), cg(3)) ! omega
410  s_time= hecmw_wtime()
411  call hecmw_allreduce_r(hecmesh, cg, 3, hecmw_sum)
412  e_time= hecmw_wtime()
413  tcomm = tcomm + e_time - s_time
414  gamma1 = cg(3)/cg(1) ! omega / myu
415  gamma2 = cg(2)/cg(1) ! nyu / myu
416  !!! COMMENTED OUT because no convergence obtained with following updates.
417  ! do j= 1, NNDOF
418  ! WW(j,T )= WW(j,T ) - gamma1*WW(j,Y)
419  ! WW(j,TT)= WW(j,TT) - gamma2*WW(j,Y)
420  ! enddo
421  endif
422 
423  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,t ), ww(:,t ), cg(1)) ! |r|^2
424  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,tt), ww(:,tt), cg(2)) ! |s|^2
425  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,t ), ww(:,tt), cg(3)) ! r.s
426  s_time= hecmw_wtime()
427  call hecmw_allreduce_r(hecmesh, cg, 3, hecmw_sum)
428  e_time= hecmw_wtime()
429  tcomm = tcomm + e_time - s_time
430 
431  c = cg(3) / dsqrt(cg(1)*cg(2))
432  c_abs = dabs(c)
433  if (c_abs > omega) then
434  qsi = c * dsqrt(cg(1)/cg(2))
435  else
436  ! QSI = (c / c_abs) * OMEGA * dsqrt(CG(1)/CG(2))
437  if (c >= 0.d0) then
438  qsi = omega * dsqrt(cg(1)/cg(2))
439  else
440  qsi = -omega * dsqrt(cg(1)/cg(2))
441  endif
442  endif
443  eta = gamma1 - qsi*gamma2
444  end subroutine pol_coef_vanilla
445 
446  !C
447  !C*** pol_coef_vanilla2 : optimized version of pol_coef_vanilla
448  !C
449  subroutine pol_coef_vanilla2(iter, WW, T, TT, Y, QSI, ETA)
450  implicit none
451  integer(kind=kint), intent(in) :: iter
452  real(kind=kreal), intent(inout) :: ww(:,:)
453  integer(kind=kint), intent(in) :: T, TT, Y
454  real(kind=kreal), intent(out) :: qsi, eta
455 
456  real(kind=kreal), dimension(6) :: cg
457  real(kind=kreal) :: gamma1, gamma2
458  real(kind=kreal) :: c, c_abs
459 
460  real(kind=kreal), parameter :: omega = 0.707106781d0
461 
462  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,t ), ww(:,t ), cg(1)) ! |r|^2
463  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,tt), ww(:,tt), cg(2)) ! |s|^2
464  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,t ), ww(:,tt), cg(3)) ! r.s
465 
466  if (iter.gt.1) then
467  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,y ), cg(4)) ! myu
468  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,tt), cg(5)) ! nyu
469  call hecmw_innerproduct_r_nocomm(hecmesh, ndof, ww(:,y ), ww(:,t ), cg(6)) ! omega
470  s_time= hecmw_wtime()
471  call hecmw_allreduce_r(hecmesh, cg, 6, hecmw_sum)
472  e_time= hecmw_wtime()
473  tcomm = tcomm + e_time - s_time
474  gamma1 = cg(6)/cg(4) ! omega / myu
475  gamma2 = cg(5)/cg(4) ! nyu / myu
476  else
477  s_time= hecmw_wtime()
478  call hecmw_allreduce_r(hecmesh, cg, 3, hecmw_sum)
479  e_time= hecmw_wtime()
480  tcomm = tcomm + e_time - s_time
481  gamma1 = 0.d0
482  gamma2 = 0.d0
483  endif
484 
485  c = cg(3) / dsqrt(cg(1)*cg(2))
486  c_abs = dabs(c)
487  if (c_abs > omega) then
488  qsi = c * dsqrt(cg(1)/cg(2))
489  else
490  if (c >= 0.d0) then
491  qsi = omega * dsqrt(cg(1)/cg(2))
492  else
493  qsi = -omega * dsqrt(cg(1)/cg(2))
494  endif
495  endif
496  eta = gamma1 - qsi*gamma2
497  end subroutine pol_coef_vanilla2
498 
499  end subroutine hecmw_solve_gpbicg
500 
501 end module hecmw_solver_gpbicg
subroutine pol_coef(iter, WW, T, TT, Y, QSI, ETA)
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_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_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